2014-03-07 22 views
0

套接字一般可以雙向通信,因此可以使用相同的套接字sendrecv
如果我想在套接字讀取時發送一些數據(在另一個線程上),那麼內核會做什麼?這適用於這兩個部分。考慮這個例子:服務器是send給你一個文件,並說它會花費很多(低上行鏈接或非常大的文件)。用戶感到無聊,並決定給你SIGINT。你抓住它並告訴服務器停止發送文件(帶有某種消息)。
即使您正在閱讀,您是否能夠發送通知服務器停止發送?當然,這也適用於服務器端。套接字數據競賽

希望我已經足夠清楚。

+4

雙工通信的討論和示例代碼允許發送和在同一時間接收......此外,如果你不能夠告訴你關閉套接字服務器,它會引起巨大的掛起。 –

+0

那麼我會說你讀寫不同的過程(fork())和不同的管道,所以我沒有看到問題?告訴我,如果我錯了 – 2014-03-07 13:53:00

+0

@梅耶你錯了。 –

回答

1

如果我想在套接字被讀取時發送一些數據(在另一個線程上),那麼內核會做什麼?

沒什麼特別的......插座不喜歡花園軟管...有隻是一些元數據添加到這就是機器之間發送的數據包,所以閱讀和寫作獨立於可能發生的(除了如果一方由於the Nagle algorithm而在本地緩衝區中存在未發送數據的套接字上調用recv(),該套接字將數據合併爲合理大小的數據包,它可能會立即超時併發送任何可能的數據,但任何調整都將是一個實現延遲調優細節,並不會改變整個圖像或客戶端和服務器調用TCP API的方式)。

考慮一下這個例子:服務器向你發送一個文件,並說它會花費很多(低上行鏈路或非常大的文件)。用戶感到無聊,並決定讓你信號。你抓住它並告訴服務器停止發送文件(帶有某種消息)。即使您正在閱讀,您是否能夠發送通知服務器停止發送?當然,這也適用於服務器端。

內核接受有限數量的數據發送,接收到的數據量有限,之後它迫使發送端等待,直到發送端發送更多數據爲止。因此,如果您已經將數據發送到服務器,然後獲取本地SIGINT並以相同的方式發送「哦,取消該數據」,則服務器必須讀取所有已發送的數據,然後才能看到「哦,取消那」。如果不是以「同樣的方式」發送它,而是在發送取消消息時打開帶外(OOB)標誌,則服務器可以(如果寫入的話)檢測到存在OOB數據並在它讀取之前讀取它完成讀取/處理其他數據。它仍然需要讀取並丟棄已發送的任何帶內數據,但上面提到的流控制/緩衝意味着應該是可管理的數量 - 遠小於文件大小。在所有這一切,無論你想recv或服務器發送是獨立的,不受大客戶端 - >服務器發送,任何OOB數據等。

有從GNU在http://www.gnu.org/software/libc/manual/html_node/Out_002dof_002dBand-Data.html

+0

@黑色號碼當你打電話給某人時,你想要兩部電話嗎?你只需要編寫代碼,看看它的工作,並停止擔心! ;-) –

1

線程1可以安全地寫入套接字(使用send),而線程2從套接字讀取(使用recv)。你需要注意的是,在線程同步的地方,否則文件描述符可能在其他地方使用,所以另一個線程(如果不是同步的話)可以從現在用於某事的文件描述符讀取其他。達到此目的的一種方法是將讀取線程的文件描述符設置爲shutdown,這應該會導致另一端斷開連接,從而導致錯誤正在進行中send