2014-10-09 25 views
1

我正在嘗試編寫一個基本的文件服務器,它從客戶端獲取一個文件名,並通過TCP向客戶端發送數據作出響應。我的大部分工作的客戶端和服務器應用程序,但我觀察了一些奇怪的行爲,請考慮以下C套接字:write()後跟close()導致數據傳輸不完整

while ((num_read = read (file_fd, file_buffer, sizeof (file_buffer))) > 0) 
    { 
     if (num_read != write (conn_fd, article_buffer, num_read)) 
     { 
      perror ("write"); 
      goto out; 
     } 
    } 
    out: 
      close(file_fd); close(sub_fd); 

file_fd的文件描述符的文件正在通過網絡發送,conn_fd是一個文件描述符到connect()編輯TCP插座。

這似乎適用於小文件,但是當我的文件變大(兆字節+)時,似乎文件末尾的一些不一致的數據量將無法傳輸。

我懷疑在寫入之後立即關閉()語句可能與它有關,所以我在close()語句和我的客戶端成功接收了所有數據之前,嘗試了1秒sleep()

有沒有更好的方法來處理這個問題,而不是在服務器端做一個sleep()

+0

您是在這裏演示了客戶端代碼還是服務器代碼? – abiessu 2014-10-09 03:57:59

+0

'fsync(2)'怎麼樣? – findall 2014-10-09 04:00:41

+0

我嘗試了fsync(),但沒有解決問題。 – user2278457 2014-10-09 04:01:11

回答

0

套接字上的成功「寫入」並不意味着數據已成功發送到對等體。

如果你是在UNIX deriviative,您可以執行「人7座」,並檢查SO_LINGER」作爲一個潛在的解決方案

編輯:由於EJP的評論(謝謝),我重讀什麼史蒂文斯說一下在保證的傳送所有數據到對等的「UNIX網絡編程」的主題他說以下內容(第二版第1卷,第189頁)。

......我們看到,當我們關閉連接的結束,具體取決於調用的函數(關閉或關閉)以及他是否設置了SO_LINGER套接字選項,返回可能發生在三個不同的時間。

  1. 立即關閉返回,不需要等待(默認值;圖7.6)
  2. 接近徘徊,直到收到我們的FIN的ACK(圖7.7),或者接着讀等待
  3. 關機,直到我們收到對端的FIN(圖7.8)

他數字和他的評論,指示除了「應用程序級別確認」以外,shutdown()的組合,然後是read()等待零返回碼(即通知套接字已關閉),這是確保客戶機應用程序的唯一方法已收到數據。

但是,如果只有數據成功傳送(並確認)對方的計算機纔是重要的,那麼SO_LINGER就足夠了。

+0

SO_LINGER並沒有真正解決這個問題,它只是在最終的待處理數據無法寫入時才能檢測*。在這種情況下,問題幾乎可以肯定是在接收端。 – EJP 2014-10-09 07:01:59