Мой сервер должен отправить клиенту два изображения размером 500 КБ. Клиент получает первое изображение нормально без потери каких-либо данных, но когда сервер отправляет другое изображение клиенту, recv () возвращает 0 до того, как данные отправлены с сервера, и сразу после этого сервер send () возвращает -1 ,
Вот мой код send () и recv ():
Сервер:
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);
Этот код запускается дважды для отправки двух изображений.
Клиент:
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);
Этот код запускается дважды, чтобы получить два изображения.
Когда я ставлю Sleep () после send () на сервер, клиент получает все данные и все изображения, но Sleep зависит от клиентской сети. и сервер получает много клиентов.
Соединение используется с TCP.
recv()
возвращает 0, когда другая сторона отключилась изящно. Помните, что TCP — это поток байтов. У него нет концепции сообщений, как у UDP. Скорее всего, ваше второе изображение хранится в том же буфере, который вы используете для первого вызова recv()
, Вам необходимо сформировать данные, например, отправить длину файла до того, как отправлять данные файла. Таким образом, получатель может сначала прочитать длину, а затем прочитать столько байтов, сколько говорит длина. Вы пытаетесь это сделать, но не очень хорошо справляетесь с этим. Для начала вы используете строку переменной длины для отправки длины файла. Это не очень хорошая идея, потому что вы не отправляете длину строки, и получатель не ищет нулевой терминатор, поэтому получатель не знает, какова длина строки, и, вероятно, читает слишком много байтов. Вы должны отправить длину файла в виде 4-х байтов фиксированной длины int
или 8 байт __int64
вместо. Это будет намного легче для получателя читать.
Других решений пока нет …