2012-10-06 62 views
2

我的服務器需要向客戶端發送兩個大小爲500kb的圖像。客戶端在沒有丟失任何數據的情況下接收到第一張圖像,但是當服務器將其他圖像發送給客戶端時,recv()在從服務器發送數據之前返回0,並且服務器send()返回-1 。套接字接收大數據後,recv()返回0

這裏是我的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); 

此代碼運行兩次收到兩個圖像。

當我將send()後的Sleep()放入服務器時,客戶端會收到所有數據和所有圖像,但睡眠取決於客戶端網絡。而服務器獲得了很多客戶。 連接與TCP一起使用。

回答

1

recv()當對方正常斷開連接時返回0。請記住,TCP是一個字節流。它沒有像UDP那樣的消息的概念。很可能,您的第二張圖像存儲在第一次撥打recv()時所用的緩衝區中。您需要構建數據,例如在發送文件數據之前發送文件的長度。這樣,接收器可以首先讀取長度,然後只讀取長度所述的字節數。你正在努力做到這一點,但你沒有很好地管理它。對於初學者,您正在使用可變長度的字符串來發送文件長度。這不是一個好主意,因爲你沒有發送字符串長度,並且接收者沒有查找空終止符,所以接收者不知道字符串有多長,並且可能讀取了太多的字節。您應該將文件長度發送爲固定長度的4字節的int或8字節的__int64。接收器讀取會更容易。

+0

我如何發送()文件的長度爲int? – eilonmore

+0

像這樣:'int filesize = ...;發送(sConnect,(char *)&filesize,sizeof(int),0);'然後在接收端:'int filesize; recv(sConnect,(char *)&filesize,sizeof(int),0);'。這假定阻塞套接字。如果您使用非阻塞套接字,則必須調整此邏輯以解釋「EAGAIN」/「EWOULDBLOCK」錯誤,但核心概念仍然適用。 –