2014-07-23 26 views
2

我想在C中編寫小文件傳輸程序(我正在使用Linux)。 我對套接字編程相當陌生,但我已經設法編寫一點服務器和客戶端程序。獲取套接字讀取操作的進度

我的問題:

如果我有這樣的事情:

int read_bytes = read(socket_id, buffer, 4096);

雖然從插座上讀書,我怎麼能得到閱讀的進展如何? 例如,我想每隔100ms顯示有多少個字節已經被傳送到目前爲止 。我很確定我必須在這裏使用線程或其他異步函數。 有沒有功能,我可以得到number of bytes readnumber of bytes to read

更新1: 積累閱讀()

int total_read_bytes=0, read_bytes; 
char buffer[4096]; 
do { 
    read_bytes = read(socket_id, buffer, 4096); 
    total_read_bytes += read_bytes; 
} while(read_bytes > 0); /* Read to end or read failed */ 

這不是非常非常低效? (例如傳輸一個1MiB文件)

謝謝

+0

您需要計算每次調用讀取多個字節到read/reicv並報告總預期值 – quantdev

+5

您可以使用較小的緩衝區大小對讀取進行細化。這將根據情況而變得高效或低效。 – Krumia

+0

你可以跳過使用線程,如果你使套接字非阻塞 – Asaf

回答

1

如果你有控制的服務器和客戶端的代碼,你可以讓發送方告訴接收的文件的大小其實之前發送文件。例如,使用消息中的前8個字節。這是number of bytes to read

通過累積在你的榜樣的read_bytes,你可以得到number of bytes read

+0

你是什麼意思與「積累」? 你的意思是在循環中調用read()? – pentix

+0

@pentix:無論如何你想要:在一個循環中,作爲一個類成員可變,等 – GuLearn

1

每個recv通話將阻止它的閱讀一些多,直到,但它不會(默認/ SANS MSG_WAITALL)等提供的緩衝區充滿。這意味着沒有必要減小緩衝區大小,以便更頻繁地更新總字節讀取信息,您可以平均保留總數爲recv()的返回值,這些值隨數據包到達而更新(或與應用程序一樣快地處理它們來自OS緩衝區)。正如你所看到的,如果總數每秒更新100次,你可能不希望發佈100次屏幕更新,而是希望限制它們到100ms的最小間隔。您可以使用計時器/鬧鐘來管理該事件,但是您有更多的邊緣情況來查看計時器是否已經掛起等等。使用兩個線程可能會更簡單:定期檢查是否需要更新:

  • thread1:
    • while((n_bytes = recv(...))> 0)
      • total_bytes + = n_bytes;
    • 設定畫面更新器終止標誌
  • 線程2:
    • last_total_bytes = -1;
    • 而屏幕更新終止標誌沒有設置
      • 睡眠100ms的
      • 如果last_total_bytes!= TOTAL_BYTES
        • 更新屏幕
        • last_total_bytes = TOTAL_BYTES

當然,您需要使用互斥鎖或原子操作來協調這些操作。

是否有一個函數,所以我可以得到...讀取的字節數?

不是來自TCP本身 - 它沒有消息大小的概念,API只是確保應用程序按照它們發送的相同順序接收字節。如果您希望能夠顯示「迄今爲止收到的N個字節,預期的X更多」,那麼在應用協議層面,發送端應該將數據前綴爲邏輯消息的大小 - 通常以固定寬度二進制格式(理想情況下使用htonl或類似的發送和接收方ntohl以避免endian問題),或在一個文本的表示,這是一個已知的哨兵字符與數據固定或分離(例如NUL,空格或換行符)。

+2

沒有必要引入多個線程或定時器/警報只是爲了限制發送屏幕更新的速率。相反,當recv()返回時,只需檢查當前時間(通過clock_gettime()的times()或其他一些毫秒級或更高分辨率的時鐘API),查看自上次屏幕顯示以來是否已經超過100mS,更新被觸發。如果是,觸發另一個屏幕更新;否則不要。 –

+0

+1提到需要'htonl'。我忘了網絡字節順序。 – pentix

+0

@JeremyFriesner:錯誤 - 說第二個'recv'在第一個和第三個10秒之後返回50ms,使用你的方法,第二個'recv'讀取的字節不會立即被合併到屏幕上,自第一次以來的100ms以後 - 只有第三次「recv」才能讓事情重新回到正軌。使用TCP時,可能會出現突發峯值,因爲丟失或延遲的數據包可以使先前接收到的但後來排序的數據包「接收」。在這些問題上真正的準確性是否有用是值得商榷的,但這就是問題所要求的...... –