【发布时间】:2011-07-04 08:36:54
【问题描述】:
.NET 中的 Socket 类公开了以下方法:
Socket.BeginSend Method (IList<ArraySegment<Byte>>, SocketFlags, AsyncCallback, Object)
我有一个 BufferManager 类,它返回指定大小为 2kB 的 ArraySegment<byte>。现在我有一条消息要发送,假设它有 10kB 大,所以我可以使用 5 个预分配的缓冲区来存储这条消息并调用Socket.BeginSend(IList<ArraySegment>>...)。这条消息会自动发送吗,就像我只使用 byte[] 时一样(即多个并行 BeginSend 操作不会在远程站点上混合消息)?
编辑:澄清一下——我正在使用 TCP/IP 套接字,我的程序同时从多个线程调用 BeginSend。
假设我们有两个数组段列表:
L1: a1 a2 a3
L2: b1 b2 b3
现在我同时从两个线程调用 BeginSend(L1...) 和 BeginSend (L2...)。我想知道这两个列表是否不会在远程端混合,我不会读到类似的内容:a1 b1 b2 a2 b3 a3。
【问题讨论】:
-
“原子”是什么意思?顺序将得到保证,但我不认为这是线程安全的。
-
套接字对“原子”的概念一无所知。他们是非常低级的。如果您需要这样的保证,那么您需要提高抽象级别并使用 WCF 之类的东西。
-
@John Saunders 我知道套接字没有原子性的概念,但是当我调用 Send(byte[]) 时,我确信发送的字节将“不间断”地到达消息和正确的顺序(尽管它们可能以多个 TCP 数据包和另一个数据包的形式出现,具体取决于 MTA 设置)。我只想知道在使用 BeginSend (IList
) 时是否可以指望相同的行为 -
@Henk Holterman 所以顺序是有保证的——当我调用两个 BeginSend 时,我可以确定远程端不会收到假设:来自第一个 BeginSend 的两个元素,另一个元素的所有元素一个,以及第一个列表中的其余元素?
-
@paszczi 所以让我们进一步分解你的问题;如果您可以保证原子性,这将意味着第一个写入的线程必须如何进入底层套接字的队列,在有机会时抓住套接字,然后坚持在等待其缓冲区刷新足够时间的同时发送所有字节序列。这样的机制当然不是我希望看到在像 Socket 这样低级的东西中实现的东西。