2009-12-30 19 views
96
  1. 我們可以在同一個套接字上調用一個線程發送並從另一個線程接收recv嗎?
  2. 我們可以從同一套接字上的不同線程並行調用多個發送嗎?

我知道一個好的設計應該避免這種情況,但我不清楚這些系統API的行爲。我也無法找到相同的好文檔。在同一個套接字上並行調用send/recv是否有效?

任何方向的指針都會有幫助。

+0

你爲什麼聲稱這樣做是不好的做法?它對我來說看起來很好,因爲你在不同的線程中收聽。 – TheMathNoob 2017-09-02 02:22:47

回答

72

POSIX將send/recv定義爲原子操作,因此假設您在討論POSIX send/recv,那麼可以,您可以從多個線程同時調用它們,並且事情將起作用。

這並不一定意味着它們將並行執行 - 在多次發送的情況下,第二次可能會阻塞,直到第一次完成。您可能不會注意到這一點,因爲發送完成後,它將其數據放入套接字緩衝區。

如果你使用的是SOCK_STREAM套接字,試圖做並行事情的可能性不大,因爲send/recv可能只發送或接收消息的一部分,這意味着事情可能會分裂。

阻塞SOCK_STREAM套接字上的發送/接收只會阻塞,直到它們發送或接收至少1個字節爲止,因此阻塞和非阻塞之間的差異無用。

+0

怎樣阻止send/recv?他們是原子嗎? – Jay 2009-12-30 18:16:38

+0

這篇文章(http://www.almaden.ibm.com/cs/people/marksmith/sendmsg.html)似乎證實了你對SOCK_STREAM的評論,但對於SOCK_DGRAM並不清楚,你究竟從哪裏得到了你的信息? – 2010-05-15 18:22:48

+1

@Joao:SOCK_DGRAM套接字被記錄爲「保留消息邊界」,這不是很清楚。從查看linux內核源代碼,您至少可以看到每個send和recv都以原子方式處理單個數據包(至少對於udp)。 – 2010-05-16 02:33:38

2

我不明白如何接收並行可能完成任何事情。如果你有一個3字節的消息,1個線程可以得到前2個字節,而另一個線程可以得到最後一個字節,但你無法分辨哪個是哪個。除非你的消息只有一個字節長,否則你無法可靠地使任何接收多線程的東西工作。

多次發送可能工作,如果您在一次通話中發送了整條消息,但我不確定。有可能會覆蓋另一個。這樣做肯定沒有任何性能優勢。

如果需要發送多個線程,則應該實現一個同步的消息隊列。有一個線程可以執行從隊列中讀取消息並讓其他線程排隊整個消息的實際發送。同樣的事情可以用於接收,但接收線程必須知道消息的格式,以便它可以正確地反序列化它們。

+6

如果您使用SOCK_DGRAM套接字,每個recv都會得到一個數據報;它將永遠不會在recvs之間分裂 – 2009-12-30 17:47:57

+2

@noah,我同意平行recvs無法完成任何事情。這就是爲什麼我沒有問過它。我的問題是發送/ recv並行,然後多個並行發送。您的回答確實可以讓您瞭解並行發送。謝謝你的一樣。 – Jay 2009-12-30 17:49:42

+1

@Chris好點。我正在假設TCP。 @Jay你可能會澄清一個問題,「我們可以調用send/recv並行」聽起來像你想並行接收。 – noah 2009-12-30 17:56:41

11

套接字描述符屬於進程,而不屬於特定的線程。因此,可以在不同線程中發送/接收同一個套接字,操作系統將處理同步。然而,如果發送/接收的順序在語義上是重要的,那麼你自己(分別是你的代碼)必須確保在不同線程中的操作之間正確的順序 - 線程總是如此。

相關問題