【发布时间】:2014-11-08 02:09:19
【问题描述】:
从套接字异步接收数据 .Net 支持对称的 BeginReceive/EndReceive 调用。基本上,您调用BeginReceive() 开始监听并确定数据到达时应调用的回调。在回调中调用EndReceive() 来提取数据并结束异步读取操作。
我正在编写 C#/.Net 软件来控制一些工业设备。控制面板允许用户设置和初始化设备,一旦它被初始化BeginReceive() 被称为开始监听数据。在回调中EndReceive() 用于提取数据,但我想立即恢复收听,所以我想我应该在完成EndReceive() 之后再次调用BeginReceive()。这是正确的吗?
如果是这样,我是否可以在代码的其他地方使用检查或测试来了解是否已经调用了 BeginReceive(),所以我不会尝试在同一个套接字上连续调用 BeginReceive() 两次,之前EndReceive() 已被调用?
【问题讨论】:
-
没错。我不知道您是否可以检查它是否已经被调用(除了您自己的自定义标志)。很可能两次调用
BeginRecieve无论如何都不会做任何事情;检查文档。 -
Socket,或者更确切地说是操作系统,会自行检查。如果您尝试在另一个接收已经在进行时调用BeginReceive,它将引发表示套接字错误 WSAEALREADY 的异常(我认为)。毕竟,尝试同时从同一个套接字接收两个缓冲区没有多大意义!但是如果你问Socket上是否有一个属性告诉你操作是否正在进行,答案是否定的(因为不可避免的竞争条件,它无论如何都没用)。如果需要,您可以实现自己的锁定。 -
您不应该以会导致重入的方式调用 begin receive .. 这是肯定的。如果您遇到需要一个标志来知道您是否调用它的情况 - 这可能意味着您的架构不正确。
-
@AntonTykhyy:“如果您尝试在另一个接收正在进行时调用 BeginReceive,它将引发异常”这是不正确的。实际上,发出多次接收操作(即多次调用
BeginReceive())是处理基于IOCP的I/O(如Socket类)时常用的策略。诀窍是,虽然缓冲区将按照它们通过接收操作提交的顺序填充,但完成事件可能会乱序发生。所以调用者确实需要跟踪他们的缓冲顺序并确保它们被正确处理。 -
欢迎查看我在 Github 上的 .NET Sockets 存储库,它使用了 BeingReceive/EndReceive 模式。 here 是 C# 版本。