【问题标题】:post many wsasend on the same socket from multiple threads从多个线程在同一个套接字上发布许多 wsasend
【发布时间】:2014-11-20 17:18:54
【问题描述】:

(问题复制自msdn论坛)

MSDN 是这样说的:

如果您使用 I/O 完成端口,请注意 对 WSASend 的调用也是缓冲区的顺序 人口稠密。不应在同一个套接字上调用 WSASend 同时来自不同的线程,因为它可能导致 不可预知的缓冲顺序。

好的...但是如果我不关心这个订单并且也不关心订单我会在另一边收到它...那我可以使用它吗?从多个线程调用 WSASend 是否安全?包裹是否会按照我传递的方式交付(可能订购方式不同,但完整)??

例如-> 我发送 [12a]、[34b]、[11c] 和 [223d] ...([] 标记我在一次呼叫中传递给 WSASend 的单元)然后我会收到例如34b、11c、12a、223d ?或者它会崩溃吗?或者我能收到像 2a, 34b, 7a, 5c, ...

所以,也许问题应该是 -> 它是线程安全的吗?它是原子的吗? (我说的是与 IOCP 一起使用的 WSASend,所以重叠)

【问题讨论】:

  • IIRC 是的,你可以这样做。这样的调用是线程安全的,但不是 TCP 安全的:)
  • 想一想——WSARecv() 调用同一套接字返回的两个缓冲区并由两个不同的池线程处理是不寻常的,但并非不可能。处理完缓冲区数据后,这些线程可能会发出 WSASend 调用以“同时”将回复发送到一个套接字。所以是的,它们必须是线程安全的。
  • 我的场景更可能使用 UDP 协议,因为两个池线程获得需要回复的完整数据报的机会将高于 TCP。
  • @Martin James 感谢回复。你说的 TCP 安全是什么意思?在我的服务器(tcp)中,经常出现一种情况,当来自多个线程的同一个套接字上的许多 wsasend 被发布时(一个 wsasend - 一条短消息(最多 30 个字节),我也不关心缓冲区顺序,客户端也不关心)。

标签: c++ multithreading sockets send iocp


【解决方案1】:

似乎实际上对 WSASend() 的调用不是线程安全的,如果您打算从同一连接上的多个线程调用 WSASend(),那么您应该进行同步,以便在任何时候只有一个线程实际调用 API给定点(即在 WSASend() 调用周围保持每个连接锁定)。详见本题及附上的测试代码:TCP/IP IOCP received data sometimes corrupt - Visual C++ on Windowsthis blog entry 更详细的解释。

另请注意,如果您使用来自多个线程的多个 WSASend() 调用发送不同的应用程序级消息,那么您会遇到问题,因为多个调用可能在数据写入 TCP 流之前混合在一起。

所以,

如果您有 5 个线程发送“完整的 2 字节消息”以便您发送

来自 5 个不同线程的 AA、BB、CC、DD、EE 等,那么您将不会得到包含

的流

ABCCDDBAEE

但你可以得到消息顺序的任意组合。

如果您的线程使用多个发送调用发送消息,例如三个发送,来自线程 1 的 A1 A2 A3 形成单个应用程序级消息。然后所有的赌注都结束了,你可能会得到 ​​p>

TCP 流中的 A1B1A2A3B2B3 等。

如果您需要稍后执行此操作,您将需要对所有 WSASend 调用进行某种锁定,以便您可以将多个发送分组为单个应用程序级别的原子发送,或者您应该为单个 WSASend 使用多个 WSABUF调用将多个写入聚集到一个调用中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 2013-03-10
    • 2016-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多