并发调用同一套接字上的send/recv是否有效?

Jay*_*Jay 119 c sockets networking

  1. 我们可以在同一个套接字上调用一个线程的发送和另一个线程的recv吗?
  2. 我们可以从同一个套接字上的不同线程并行调用多个发送吗?

我知道一个好的设计应该避免这种情况,但我不清楚这些系统API将如何表现.我也找不到相同的好文档.

方向上的任何指针都会有所帮助.

Chr*_*odd 86

POSIX将send/recv定义为原子操作,所以假设您正在谈论POSIX send/recv然后是,您可以从多个线程同时调用它们,事情就可以了.

这并不一定意味着它们将并行执行 - 在多次发送的情况下,第二次可能会阻塞直到第一次完成.您可能不会注意到这一点,因为一旦将数据放入套接字缓冲区,发送就会完成.

如果您正在使用SOCK_STREAM套接字,那么尝试并行操作不太可能有用,因为send/recv可能只发送或接收部分消息,这意味着事情可能会被拆分.

阻止SOCK_STREAM套接字上的send/recv只会阻塞,直到它们发送或recv至少1个字节为止,因此阻塞和非阻塞之间的区别无用.

  • @ChrisDodd,你能给"POSIX定义send/recv作为原子操作"的链接吗? (6认同)
  • @Joao:SOCK_DGRAM 套接字被记录为“保留消息边界”,这不是很清楚。通过查看 linux 内核源代码,您至少可以看到每个 send 和 recv 以原子方式处理单个数据包(至少对于 udp)。 (4认同)
  • @suitianshi:POSIX 1003.1c 标准文档列出了 1003.1 中可重入(从线程调用安全)和不可重入的所有函数。不幸的是,我不知道任何地方都有免费的在线副本。 (4认同)
  • @Kedar:不确定你的意思。一旦数据被放入发送缓冲区,“send”就会返回,并且数据通过 netowrk 堆栈发送并异步发送到网络上。因此,如果您有一个线程发送和一个线程接收,则发送线程完全有可能(甚至可能)在接收线程收到第一个数据包之前发送许多数据包。它完全是异步的而不是同时的。 (3认同)
  • @ChrisDodd我在http://www.unix-systems.org/version4/上找到了副本,我可以在7.1章看到系统接口表的列表,但是看不到它在哪里列出了作为原子操作的功能。不用怀疑,但是您可以分享/编辑您的答案以证明您在文档中的观点正确吗? (2认同)

Adr*_*her 17

套接字描述符属于进程,而不属于特定线程.因此,可以在不同的线程中向/从相同的套接字发送/接收,OS将处理同步.

但是,如果发送/接收的顺序在语义上很重要,那么您自己(分别是您的代码)必须确保在不同线程中的操作之间进行正确的排序 - 就像线程一样.