2
votes

My server needs to send two images with size of 500kb to the client. The client receives the first image fine without losing any data, but when the server sends the other image to the client, recv() returns 0 before the data is sent from the server, and right after that the server send() returns -1.

Here is my send() and recv() code:

Server:

    fp2 = fopen(totaldir2,"rb");
if(fp1==NULL)
{
    cout<<"ERROR while openning: "<<totaldir2<<endl;
    getchar();
    exit(1);
}

fseek (fp2, 0 , SEEK_END);
IFileSize2 = ftell (fp2);
rewind (fp2);
picture2 = new char[sizeof(char)*IFileSize2+1];
if (picture2 == NULL) {exit (2);}
itoa (IFileSize2,CFileSize2,10);
countData = 0;
do{
sentData = send(sConnect,CFileSize2,strlen(CFileSize2)+1,NULL);
countData+=sentData;
}while(countData<strlen(CFileSize2)+1);
read = fread_s(picture2, IFileSize2, sizeof(char),IFileSize2, fp2);
countData = 0;
do{
sentData = send(sConnect, picture2, read, 0);
countData += sentData ;
}while(countData<read);

This code runs twice to send the two images.

Client:

recv(sConnect, len2, sizeof(len2) ,NULL); \\recv returns 0 here before server sends the data.
FileSize2 = atoi(len2);
picture2 = new char[sizeof(char)*FileSize2+1];
fp2 = fopen("temp\\image2.bin","wb");
if(fp2==NULL)
{
     closesocket(sConnect);
     WSACleanup();
     exit(1);
    }

recv(sConnect, picture2, FileSize2, 0); \\same here
fwrite(picture2, sizeof(char), Received2, fp2);

This code runs twice to recieve the two images.

When I put Sleep() after send() in the server, the client receives all of the data and all of the images, but the Sleep depends on the client network. and the server gets a lot of clients. The connection is used with TCP.

1

1 Answers

1
votes

recv() returns 0 when the other party has disconnected gracefully. Remember that TCP is a byte stream. It has no concept of messages like UDP does. Most likely, your second image is being stored in the same buffer that you are using for the first call to recv(). You need to frame your data, such as sending the file's length before then sending the file data. That way, the receiver can read the length first, then read only as many bytes as the length says. You are trying to do that, but you are not managing it very well. For starters,you are using a variable-length string to send the file length. That is not a good idea, because you are not sending the string length, and the receiver is not looking for the null terminator, so the receiver does not know how long the string is and likely reads too many bytes. You should send the file length as a fixed-length 4-byte int or 8-byte __int64 instead. That will be much easier for the receiver to read.