2011-12-27 13 views
1

更新: 我添加了一個while以獲取剩餘數據,解決了問題。謝謝你們。我通過套接字發送C結構,但無法正確地完成,總是會丟失一些字節

while(res != rcvread->size + 4) {/* do not get full data */ 
    tmp = recv(connfd, (void *)rcvread + res, rcvread->size + 4 - res, 0); 
    if(tmp == -1) 
     printf("error:%s\n",(char *)strerror(errno)); 
    res+=tmp; 
} 

我想通過socket發送結構mfsiowrite返回值是37772,但是當我從其他程序得到它的read返回值是32768,這是非常奇怪的。

這種結構的定義在這裏

struct mfsio{ 
    size_t size; 
    char buf[]; 
}; 

的發送代碼是在這裏

struct mfsio *sndread; 
sndread = malloc(sizeof(struct mfsio) + rcvcmd->size); 
res = pread(fd, &(sndread->buf), rcvcmd->size, rcvcmd->offset); 
sndread->size = res; 
res = write(connfd, sndread, sizeof(struct mfsio) + res); 

接收代碼是在這裏

struct mfsio *rcvread; 
rcvread = malloc(sizeof(struct mfsio) + size); 
res = 0;  
res = read(connfd, rcvread, sizeof(struct mfsio) + size); 

size等於rcvcmd->size和RES pread是32678,水庫write是32772. 但read的資源是32678.

這種情況怎麼會發生?我在這裏做錯了什麼?

如果沒有來自write輸入時,read功能只是在等待一些數據,只是掛在那裏

如果我使用一個循環來避免這樣的問題,我怎麼能最終得到了整個數據結構,我的意思是如果我循環讀取,我會從套接字中獲取剩餘的字節,但我怎樣才能將這些剪輯合併到一起?

+0

您必須將您讀入的指針調整爲循環的一部分,並在其中添加之前讀取的字節數。確保你使用這個指針算術的字符指針。 – 2011-12-27 14:14:50

+1

結構填充不可移植。您需要發送數據的序列化表示。 – u0b34a0f6ae 2011-12-27 19:06:24

+0

@ kaizer.se那麼,有沒有在Linux上的任何lib可以做到這一點?我做了一些谷歌搜索,但沒有找到。 – bxshi 2011-12-28 08:40:56

回答

8

您需要在循環中進行讀寫操作,直到讀取/寫入所有預期數據。對於閱讀,你必須閱讀,直到它返回0,表示沒有其他可用。或-1表示錯誤。

你最近的問題是,你正在使用指針運算與結構指針:

tmp = recv(connfd, rcvread + res, rcvread->size + 4 - res, 0); 

在C,當你做你不與字節的工作指針算法,但你用的大小工作對象(例如rvcread)。您應該定義一個char *,它是您讀取位置的字節位置,然後在讀取數據時更新此位置。

+0

我想得到這個結構。如果我使用循環,那麼我只能得到左邊的字節,而不是整個結構。有沒有辦法解決這個問題? – bxshi 2011-12-27 14:04:17

+1

我想你最好通過loop語句接收所有數據,就像上面的Upton的答案一樣。 – 2011-12-27 14:07:49

+0

我添加了這些代碼來獲取剩餘數據,但它返回了一個「錯誤的地址」。 \t tmp = recv(connfd,(void *)(rcvread + res),rcvread-> size + 4 - res(012) ,0); \t \t如果(TMP == -1) \t \t \t的printf( 「錯誤:%s \ n」 個,(字符*)字符串錯誤(錯誤)); \t \t res + = tmp; \t}' – bxshi 2011-12-27 15:37:33

0

readwrite對字節流進行操作。沒有保證讀取會讀寫寫入它的字節數量。使用sendmsg或將記錄大小或記錄分隔符放入流中。

0

弗朗西斯厄普頓的答案似乎是正確的,你應該遵循他的建議。
但我有另一個猜測,也許這是問題。
您不會顯示如何在接收器中獲得大小的值。一個合理的方法是從套接字讀取4個字節大小。所以如果你這樣做了,你已經讀了4個字節,並且在下一次讀取時會減少4個字節。

+0

我剛剛從我的接收器中讀取了最大可能的字節大小,並且數據等於或小於那個大小。 – bxshi 2011-12-27 14:34:54

+0

@bxshi:這個概念不起作用。發送者需要提供寫入的_actual_大小,否則您無法在讀者端確定要讀取的字節數。 – 2011-12-27 14:38:58

0

recv()標誌MSG_WAITALL也可能會感興趣,因爲它基本上整個

while (!allDataReceived) { 
    receiveMoreData(); 
} 

東西給你。

但是,其他答案暗示你應該發送一個標題爲「這是多少字節將遵循」,這絕對是你應該聽的東西。

相關問題