C++ socket中recv和send機制
阿新 • • 發佈:2019-02-07
利用TCP傳遞資訊時要注意:TCP傳輸是流的方式:即send 100個位元組後對方如果沒有及時recv取出,
這時又send 100個位元組,則recv有可能接收到兩次傳送疊加的部分或全部資料,所有在傳送結構體資料
時,應當傳送以後睡眠一段時間,使對方recv有足夠的實際取走資料,不至於兩個結構體資料發生粘連,
區分不出傳送的是兩個結構體資料。
另外,send(SOCKET,BUFF,SIZE,FLAG)傳送的資料將存放到系統緩衝區,當系統緩衝區已滿時,
send將返回傳送的位元組數,這時傳送的位元組數並不是SIZE大小了,同理,recv(SOCKET,BUFF,SIZE,FLAG)
每次接受的資料也不一定是SIZE大小,而是返回的值大小的位元組。故傳送和接收大檔案即檔案的大小大於SIZE時
可利用如下程式碼執行:
bool Server::SendFile(SOCKET sd) //向客戶端傳送檔案 { cout<<"進入到傳送檔案內容"<<endl; cout<<"要傳送的檔案為"<<fileName<<endl; FILE *pFile; pFile=fopen(fileName,"r+b"); fseek(pFile,0,SEEK_SET); //定位到檔案首位置 _int64 i=0; char buff[MAX_PACK_SIZE]; cout<<"要傳送的檔案長度為"<<fileLength<<endl; while(i<fileLength) { int nSize; if(i+MAX_PACK_SIZE>fileLength) { nSize=(int)(fileLength-i); } else { nSize=MAX_PACK_SIZE-1; } fread(buff,sizeof(char),nSize,pFile); int nSend; nSend=send(sd,buff,nSize,0); if(nSend==SOCKET_ERROR) { cout<<"傳送失敗"<<WSAGetLastError()<<endl; return false; } i+=nSend; fseek(pFile,-(nSize-nSend),SEEK_CUR); //定位到實際已傳送到的位置 memset(buff,0,sizeof(char)*MAX_PACK_SIZE); //將buff清空 } fclose(pFile); return true; }
<pre name="code" class="cpp">bool Server::ReceiveFile(SOCKET sd) { char buff[MAX_PACK_SIZE]; FILE *pFile; pFile=fopen(fileName,"a+b"); _int64 i=0; while(i+1<fileLength) { int nRecv=recv(sd,buff,MAX_PACK_SIZE,0); if(nRecv==SOCKET_ERROR) { return false; } fwrite(buff,sizeof(char),nRecv,pFile); i+=nRecv; memset(buff,0,sizeof(char)*MAX_PACK_SIZE); } fclose(pFile); return true; }