套接字数据竞争

时间:2014-03-07 13:45:56

标签: c++ linux sockets

套接字通常可以双向通信,因此同一个套接字可用于sendrecv
如果我想在读取套接字时发送一些数据(在另一个线程上),那么内核会做什么?这适用于两个部分。

考虑这个例子:服务器send给你一个文件并说它需要很多(低上行链路或非常大的文件)。用户感到无聊并决定SIGINT你。你抓住它并告诉服务器停止发送文件(带有某种消息) 即使您正在阅读它,您是否能够发送告诉服务器停止发送?当然,这也适用于服务器端。

希望我已经足够清楚了。

2 个答案:

答案 0 :(得分:1)

线程1可以安全地写入套接字(使用send),而线程2从套接字读取(使用recv)。您需要注意的是,在close()套接字线程同步的位置,否则文件描述符可能在别处使用,因此另一个线程(如果未同步)可以从文件描述符中读取现在用于别的东西。实现此目的的一种方法是将您的线程读取到shutdown文件描述符,这会导致另一端丢弃连接,从而使正在进行的send错误。

答案 1 :(得分:1)

  

如果我想在读取套接字时发送一些数据(在另一个线程上),那么内核会做什么?

没什么特别的......套接字不像花园软管......只是在机器之间发送的数据包中添加了一些元数据,因此读取和写入是独立发生的(除了也许如果一方在由于the Nagle algorithm而在本地缓冲区中具有未发送数据的套接字上调用recv(),该套接字将数据合并为合理大小的数据包,则可能会立即超时并发送任何可能的内容,但是任何调整都将是一个实现延迟调整细节,并不会改变客户端和服务器调用TCP API的大图或方式。)

  

考虑这个例子:服务器正在向你发送一个文件并说它需要很多(低上行链路或非常大的文件)。用户感到无聊并决定给你SIGINT。你抓住它并告诉服务器停止发送文件(带有某种消息)。即使您正在阅读它,您是否能够发送告诉服务器停止发送?当然,这也适用于服务器端。

内核接受要发送的有限数量的数据,并接收有限数量的数据,之后它会强制发送方等待,直到某些数据已经消耗,然后再发送更多数据。因此,如果您已将数据发送到服务器,然后获取本地SIGINT并以相同方式发送“哦,取消”,服务器必须先读取所有已发送的数据,然后才能看到“哦,取消那”。如果不是“以相同的方式”发送它,而是在发送取消消息时打开带外(OOB)标志,那么服务器可以(如果写入的话)检测到有OOB数据并在它之前读取它完成阅读/处理其他数据。它仍然需要读取和丢弃您已经发送的任何带内数据,但上面提到的流量控制/缓冲意味着它应该是一个可管理的数量 - 远远低于您的文件大小。在所有这些中,无论你想要recv或服务器发送的是独立的,不受大客户端 - >服务器发送,任何OOB数据等的影响。

http://www.gnu.org/software/libc/manual/html_node/Out_002dof_002dBand-Data.html

上有来自GNU的讨论和示例代码