2011-03-15 232 views
2

我試圖降低對發送緩衝區的大小我非阻塞TCP套接字,這樣我可以正確顯示上傳進度條,但我看到一些奇怪的行爲。奇怪的行爲

我創建嵌非阻塞TCP,SO_SNDBUF設置爲1024,驗證是正確設置,然後連接(在此之前試過和呼叫後沒什麼區別連接)。

問題是,當我的應用程序實際出現並調用發送(發送約2MB)而不是返回大約發送1024字節時,發送調用顯然接受所有數據並返回2 MB的發送值我通過的)。一切正常運行(這是一個HTTP PUT,我得到一個響應等),但我最終顯示在我的進度條是上傳坐在100%約30秒,然後響應進來。

我有證實,如果我在獲得響應之前停止,上傳並沒有完成,所以它不像它上傳得非常快,然後服務器停滯......任何想法?窗戶甚至看這個設置?

+0

SO_SNDBUF是您的發送緩衝區的最大尺寸......試圖用1 kB緩衝區一次發送2MB,聽起來有點奇怪。你應該增加你的發送緩衝區大於2MB或者發送小於1kb。我認爲你錯誤地認爲設置SO_SNDBUF會在1 kB段中「剪切」你的2 MB並逐個發送它們,你需要自己做。 – 2011-03-15 14:40:02

+0

我的印象是,它應該限制可以隨時排隊的數據量,但是,對。基本上,我只需要一個指標,表明實際傳輸了多少數據(而不是排隊)。緩衝區的大小並不是真的與我有關,我只是想挑選一些足夠小的內容,以便看到一些細節。有一個更好的方法嗎? HTTP沒有任何內置的中間上傳ACK afaik。 – Ogapo 2011-03-15 14:54:12

+0

是的,就是這樣。如果您只能排隊1KB,則不能發送2MB。爲什麼它假裝它發送2 MB是另一個問題。請記住,無論你做什麼,TCP可能很好地將你的數據包組合或分割(見Nagle)。你應該分開你自己的發送,我想你的情況應該是10到50kB。要查看正在進行的上傳,請使用Wireshark或Fiddler2之類的代理。 – 2011-03-15 15:10:44

回答

3

Windows不看此設置,但你希望它是設置不工作。 設置這些緩衝區的大小時,實際上是在設置與您通信的實際NIC上的緩衝區的大小,從而確定要傳出的數據包的大小。

您需要了解有關Windows什麼,是有你的調用代碼和實際工作NIC之間的緩衝,我不知道,你可以控制的大小。如果在套接字上調用發送操作,將數據轉儲到該套接字中,並且Windows的內核將使用緩衝區中的數據在NIC上逐步執行發送,會發生什麼情況。

這意味着代碼實際上會報告2MB beeing'sent',但這僅僅意味着您的2MB數據已成功寫入內部緩衝區,並不意味着/保證數據已經發送。

我一直在研究類似的項目與視頻流和tcp通信,這些信息是MSDN論壇和technet上的某個地方,但它需要一些真正詳細的搜索它如何實際工作。

2

我觀察到Windows上的同樣的事情,使用Java非阻塞通道。

根據http://support.microsoft.com/kb/214397

如有必要,Winsock的可緩衝比SO_SNDBUF緩衝區大小顯著更多。

這是有道理的;發送由本地機器上的程序啓動,該程序被假定爲合作而不是敵對的。如果內核具有足夠的內存,則拒絕發送數據沒有意義;無論如何,有人必須緩衝它。 (接收緩衝區用於遠程程序,這可能是敵對的)

內核確實對發送數據的緩衝存在限制。我正在製作一個服務器套接字,並且每次發送內核最多接受128K;不像你的例子中的2MB是用於客戶端套接字的。

也是根據同一篇文章,內核只有緩衝區2發送;下一個非阻塞發送應立即返回報告寫入的0字節。因此,如果我們每次只發送少量數據,程序將受到接收端的限制,並且您的進度指示器可以很好地工作。

2

該設置不會影響NIC上的任何內容;它是受影響的內核緩衝區。發送和接收都默認爲8k。

您看到的行爲的原因是:發送緩衝區大小不是您可以一次發送的數量限制,而是「標稱」緩衝區大小。當等待發送的緩衝區中仍有數據時,它僅影響後續發送。

例如:

  1. 設置的發送緩衝區,以101字節
  2. 發送10個字節,將緩衝
  3. 發送10多個字節,將緩衝
  4. ...繼續直到緩衝區中有100個字節
  5. 再發送10個字節

    此時WinSoc k使用一些邏輯來確定是否接受新的10個字節(並使緩衝區爲110個字節)或阻止。我不記得這個行爲,但它是在MSDN上。

  6. 發送10多個字節

這最後一個一定會被阻塞,直到一定的緩衝空間可用。

因此,在本質上,發送緩衝區的規模儲量和:

  • 的WinSock總是會接受緩衝區的幾乎任何大小的發送是空的
  • 如果緩衝區有數據和寫入就會溢出,有一些邏輯,以確定是否接受/拒絕
  • 如果緩衝區已滿或溢出,也不會接受新的發送

很抱歉的模糊性和缺乏聯繫;我有點匆忙,但碰巧記得我之前寫過的網絡產品的這些細節。