简体   繁体   中英

I am getting some garbage value while sending file data through socket to server? Why?

I am setting up a client server connection through sockets in C++. I am successfully connecting them but while sending filesize and file data i am receiving some garbage values also in my server.

I am firstly sending File Size through send system call from client and then sending file Buffer to server.

I have recv system call in server which is successfully receiving Filesize, but while getting File data after some bytes i am getting garbage.

Client Code

File = fopen("index.jpg", "rb");
if (!File)
{
    MessageBox(L"Error while readaing the file");

}
fseek(File, 0, SEEK_END);
Size = ftell(File);
fseek(File, 0, SEEK_SET);

char* Buffer = new char[Size];

fread(Buffer, Size, 1, File);



char cSize[MAX_PATH];
sprintf(cSize, "%lu", Size);



send(Socket, cSize, MAX_PATH, 0); // File size
send(Socket, Buffer, Size, 0); // File Binary

Server Code

          unsigned long Size;
    char *Filesize = new char[1024];

    if (recv(Sub, Filesize, 1024, 0)) // File size
    {
       Size = strtoul(Filesize, NULL, 0);  //getting filesize
    }


    Buffer = new char[Size];
    int reader = recv(Sub, Buffer, Size, 0);
    Buffer[Size] = '\0';
    if (reader == -1) // File Binary
    {
        MessageBox(L"Perror Recv");
    }
    else if (reader == 0)
    {
        MessageBox(L"Connection is Closed");
    }
    else
    {
        FILE *File;
        File = fopen("test.jpg", "wb");
        fwrite((const char*)Buffer, 1, Size, File);  
        MessageBox(L"DATA Received");
        fclose(File);
    }

One problem is that you aren't handling the return values from recv() correctly. For example:

if (recv(Sub, Filesize, 1024, 0)) // File size

... when the function quoted above returns, it has written some number of bytes (more than 0, less than 1025) into Filesize . How many? Your program doesn't know, because you didn't store the return value into a variable to find out (rather you only checked it to see if it was non-zero, or not, then discarded the value). Therefore, it's entirely likely that Filesize contains not only your file size value, but the some portion of your file's data as well... which is why that portion of your file's data won't get written to disk later on in your program.

A similar problem is here:

int reader = recv(Sub, Buffer, Size, 0);

You check reader to see if it is -1 or 0 (which is good), but in your final case you just fwrite() out Size bytes from the array, when Buffer contains reader bytes, not Size bytes (and reader could have any value between 1 and Size , depending on how many bytes the TCP stack decided to deliver to you in that particular recv() call.

One more problem is that you send MAX_PATH bytes for the file size, but you receive (up to) 1024 bytes for file size. Is MAX_PATH equal to 1024? If not, then even if recv() did fill out all 1024 bytes, your sender and receiver would still be out of sync with each other, since the excess bytes would show up in future recv() calls, or (alternatively) you'd get bytes from subsequent send() calls placed into your FileSize buffer.

So that's the direct problem -- I think the underlying problem is that you are making some assumptions about how TCP network works that are not true. In particular:

  • There is no guarantee of a one-to-one correspondence between send() and recv() calls. (TCP is a byte-stream protocol and doesn't do any data-framing)

  • You cannot rely on N bytes of data from a single call to send() being delivered via a single call to recv() . The bytes you send() will be delivered in order, but there are no guarantees about how many calls to recv() it will require to receive them all, nor about how many bytes any given call to recv() will write into your receive-buffer.

  • You cannot rely on recv() to fill up the entire buffer you passed to it. recv() will write as few or as many bytes as it wants to, and it's up to your code to handle it correctly regardless of how many bytes it gets per recv() call.

In practice, this means you'll need to call recv() in a loop, and keep careful track of the return value from each recv() call, so you always know exactly how many bytes you've received so far and therefore where inside your buffer the next recv() call should start writing at.

您没有处理 send 和 recv 函数的响应,请确保收集这些响应,因为发送和接收的字节数并进一步使用它们是必需的。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM