socket程式設計中recv的錯誤使用

2021-06-11 22:07:55 字數 1982 閱讀 1677

在昨天的測試中,終於發現了apicollector上傳樣本至executor時樣本錯誤的問題。問題原因在對socket中recv函式的理解錯誤。

之前的做法是:在傳送端apicollector首先傳送樣本的資訊至executor,包括樣本名稱、大小等,然後將樣本分成一塊一塊傳送,每塊2048位元組,在executor端收到樣本資訊後,計算資料塊的數目n,然後recv這麼多次數,每次都儲存到緩衝區data(char [buffer_length],buffer_length=2048),然後寫入檔案中,均以二進位制方式讀和寫。

一直執行都沒發現問題,後來出現了傳入的樣本無法執行的問題才了解到

在執行的過程中傳入的樣本的md5碼有時和原樣本的md5碼不同的情況。昨天詳細分析了一下兩個樣本的十六進製制內容,發現一開始的內容都是相同的。但是到中間的時候,明明是乙個塊的內容,在傳入樣本中卻被一大塊的0隔開了,而且經過多次測試,並不是在固定的地方被隔開,而且0的個數也是不定的,也就是說,原本一塊的內容中穿插了不定數目的0。問題應該在接收函式這裡,即recv函式,它的介紹如下:

從乙個套介面接收資料,表頭檔案:

#include#includeint pascal far recv( socket s, char far* buf, int len, int flags);

s:乙個標識已連線套介面的描述字。

buf:用於接收資料的緩衝區。

len:緩衝區長度。

flags:指定呼叫方式。

這裡只描述同步socket的recv函式的執行流程。當應用程式呼叫recv函式時,  

(1)recv先等待s的傳送緩衝中的資料被協議傳送完畢,如果協議在傳送s的傳送緩衝中的資料時出現網路錯誤,那麼recv函式返回socket_error

(2)如果s的傳送緩衝中沒有資料或者資料被協議成功傳送完畢後,recv先檢查套接字s的接收緩衝區,如果s接收緩衝區中沒有資料或者協議正在接收資料,那麼recv就一直等待,直到協議把資料接收完畢。當協議把資料接收完畢,recv函式就把s的接收緩衝中的資料copy到buf中(注意協議接收到的資料可能大於buf的長度,所以在這種情況下要呼叫幾次recv函式才能把s的接收緩衝中的資料copy完。recv函式僅僅是copy資料,真正的接收資料是協議來完成的),recv函式返回其實際copy的位元組數。如果recv在copy時出錯,那麼它返回socket_error;如果recv函式在等待協議接收資料時網路中斷了,那麼它返回0。

之後又查詢了一下關於大資料recv的資料。突然發現問題在我對recv這個函式的理解錯誤,apicollector一塊一塊的傳送,executor並不一定就是一塊一塊的接收的,也就是說recv接收時可能會出現一次接收不足buf的情況,當然也有可能出現多於buf的情況,因為出現了前者情況,才會使一塊中間插入了一堆0的情況,那是因為

接收不足buf,而buf每次接收資料前都memset為0了,所以將這個buf情況存到檔案中時,就出現一堆0的情況。

找到原因就好解決了,不能依靠資料塊的數目n來recv,而是通過recv的返回值,即其實際copy到buf的位元組數來判斷,即累加每次的copy的位元組數,若和大於等於檔案大小,即結束recv。如下:

ulonglong bytesall = fileinfo->filelen;

char *data = new char[buffer_length];

int bytesreceivedonce = 0; //一次接收的資料

ulonglong bytesreceivedall = 0;

while(bytesreceivedall < bytesall)

{ memset((char *)data, 0, buffer_length);

if ((bytesreceivedonce = recv(client, data, buffer_length, 0)) <= 0)

{ cout<<"socketserver: download file error!"<

修改後,經過多次測試傳入大檔案,完全正確,傳入的樣本的md5碼現在和原檔案的一樣了~

socket程式設計中應用recv判斷連線已斷開

在網路程式設計中,經常會檢測網路的連線情況,進而進行下面的動作。在linux的socket程式設計中,有一種非常方便的方法,來判斷對方是否斷開了連線,就是使用recv函式。在apue 中,對 recv的表述如下,include ssize t recv int sockfd,void buf,siz...

socket程式設計 recv 返回值處理

一般在經典的socket教程中,呼叫send 和recv 時都會判斷一下返回值,如果返回值是 1 或者socket error 那麼就進行錯誤處理 一般是列印出錯資訊,關閉socket,退出 在我的乙個專案中我因為嫌麻煩就想當然沒有判斷send和recv的返回值,結果遇到了點小麻煩。簡單地說明一下問...

socket中send函式和recv函式的理解

int send socket s,const char buf,int len,int flags 引數描述 同步 socket 的send函式的執行流程如下 如果len大於傳送緩衝區剩餘空間大小 不足放入剩餘傳送緩衝區 send就一直 等待協議把s傳送緩衝區中的資料傳送完 如果len小於傳送緩衝...