1. 程式人生 > >C++ socket中recv和send機制

C++ socket中recv和send機制

利用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;
}