2012-03-03 49 views
0

那Im上工作(這是一個Unix下C多線程非塊套接字服務器)需要從客戶端接收一個文件,並將其廣播到連接到所有其他客戶端的服務器服務器。非塊插座連續文件傳輸

一切都在那不好受林來確定當一個文件被轉移做...因爲即時通訊使用時遇到的問題文件傳輸的recv返回-1時有時無堵塞插座進出口異常的工作(這我是假設是文件的結尾),那麼下一次多個字節進來。

我嘗試破解整個事情將「END」在流的末尾。但是,有時在一行中發送多個文件時,「END」與下一個文件的開頭是同一個recv緩衝區的一部分。甚至是最糟糕的,有時我結束了與EN和下傳的d進來完成一個緩衝。

什麼是避免上述情況的最好辦法,我真的不希望每一次我從套接字循環中接收了一些字節的整個累積緩衝區,以檢查「END」是否是它的一部分,然後適當地剪切......我確定有更好的解決方案來解決這個問題嗎?

在此先感謝!

+2

在發送數據本身之前,爲什麼不先發送文件大小? – 2012-03-03 07:12:12

回答

0

最simpe情況EJP指的是,在那裏你把插座的另一端作爲檔案結尾關閉的情況下,可能看起來像以下:

{ 
    ssize_t sizeRead = 0; 

    while (sizeRead = recv(...)) { 
    if (0 > sizeRead) { /* recv() failed */ 
     if ((EGAGAIN == errno) ¦¦ (EWOULDBLOCK == errno)) { /* retry the recv() on those two kinds of error */ 
     usleep(1) /* optional */ 
     continue; 
     } 
     else 
     break; 
    } 

    ... /* process the data read ... */ 
    } 

    if (0 > sizeRead) { 
    /* There had been an error during recv() */ 
    } 
} 
2

如果recv()返回-1這是一個錯誤,您需要檢查errno。最有可能的是它是EAGAINEWOULDBLOCK,這意味着當前沒有數據在套接字接收緩衝區中。所以你需要重新選擇()。

recv()返回同行已斷開連接的插座和傳輸完成。

+0

重新選擇你的意思是什麼?我不想在等待狀態期間阻塞線程循環...我需要同時處理其他客戶端的傳輸... – McBob 2012-03-03 07:20:24

+0

@McBob我不明白。使用非阻塞I/O的全部原因是您可以在一個線程中處理多個客戶端。這就是select()的用途。當'recv()'返回-1並且'errno'爲'EAGAIN/EWOULDBLOCK'時,你繼續處理下一個準備好的FD。當你不在時,重新選擇。 – EJP 2012-03-03 08:47:05

1

信令結束某個字節序列的文件不可靠,該文件可能包含該序列。首先發送文件長度 - 如果允許大文件傳輸,則使用4字節或8字節,使用網絡字節順序。

if ((n = read(..., filelen)) > 0) { 
    filelen -= n; 
}