2009-12-30 18 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

套接字描述符属于进程,而不属于特定的线程。因此,可以在不同线程中发送/接收同一个套接字,操作系统将处理同步。然而,如果发送/接收的顺序在语义上是重要的,那么你自己(分别是你的代码)必须确保在不同线程中的操作之间正确的顺序 - 线程总是如此。

相关问题