我在 Windows Phone 7 应用程序中使用伪同步套接字。我的套接字代码基于http://msdn.microsoft.com/en-us/library/hh202858(v=vs.92).aspx中的示例。
服务器的发送模式有些不可预测。它以包含消息其余部分的长度的固定大小的标头开始。我首先读入了这个头文件,然后我从套接字中读取了指定数量的字节。
由于我还需要向服务器发送消息,并且我尝试将套接字与一个用于接收的线程和另一个用于发送的线程进行双工导致了很多问题,所以我的代码中有一个这样的循环:
while (KeepConnectionGoing)
{
byte[] Rcvd;
Rcvd = Socket.Receive();//Returns null if no message received in 50 ms
if (Rcvd != null)
{
ParseMessage(Rcvd);
}
if (HasMessageThatNeedsToBeSent())
{
byte[] Message = GetMessageToSend();
Socket.Send(Message);
}
}
这在大多数情况下都可以正常工作,但是当消息为空时会发生奇怪的事情。因为 Receive 方法中的超时(请参阅链接示例)使用 ManualResetEvent,所以套接字上的接收请求永远不会真正取消。即使该方法返回,该请求也会在某个地方等待,并且当套接字上的数据可用时,会占用头部。事件处理程序与它接收到的数据无关(因为方法已经返回并且方法中的变量永远不会再被使用),数据基本上消失了。我希望返回标头跳过的读取请求读取标头之后的字节,我不知道消息有多长。
如果套接字超时,我希望能够取消所有未完成的请求。我正在使用示例中的匿名方法,因为它简化了所有事情,并让我不必自己编写所有状态传输代码。因此,我无法解开事件处理程序。我认为,即使我使用一个方法作为事件处理程序,但在异步操作完成之前取消挂钩,仍然会调用回调方法。(我没有测试过,这只是我的理解)
现在,我能看到的唯一解决方案是将一些静态字节数组组合在一起(即具有静态字节 [] 标头,如果它为空,我会读取标头,否则我会阅读消息),但这似乎真的不优雅的解决方案并且很容易出现竞争条件。
有没有更好的办法?
谢谢