我正在开发一个使用原始 TCP 套接字与中央服务器通信的客户端应用程序。应用程序消息被序列化,然后加上长度前缀以创建传递到 TCP 流中的帧。
处理此问题的一种经典方法是直接在套接字类上调用 Receive 或 BeginReceive,在回调上反序列化消息,将消息传递到单独的队列中以供另一个线程处理,然后让回调再次在套接字上开始另一个接收。
这种方法的简单实现对我来说并不理想——它将消息序列化和反序列化与套接字紧密耦合,并且需要相当多的“管道”才能让队列在不同的线程/回调中发挥良好的作用。它也有点抽象——它需要调用代码了解底层套接字,而不是输入和输出消息的“数据流”。
鉴于我完全在 .NET 4.5 中工作,使用 TPL (TaskFactory.FromAsync) 包装 Socket 的 Begin 和 End 异步方法是一个明显的选择。但是,由于多种原因,我不清楚如何从这一点着手:
- 我需要一个永远不会完成的异步“任务”来接收数据。只要连接了套接字,我就想要处理消息流。任何中断(断开连接、套接字错误或取消请求)都将是异常,而不是传统的任务完成。根据 Stephen Toub ( http://blogs.msdn.com/b/pfxteam/archive/2011/10/02/10218999.aspx ) 的说法,我应该始终完成我的任务。这产生了一些问题——传统意义上的套接字接收永远不会完成。斯蒂芬似乎在他的“等待套接字操作”帖子中与自己略有矛盾,他在其中展示了一个套接字读取,它永远不会在没有套接字错误的情况下完成(http://blogs.msdn.com/b/pfxteam/archive/2011/12/15 /10248293.aspx)。
- 我需要一种同步“排队”要发送的数据的方法。调用者应该能够发送要传输的消息而不会阻塞,并且消息应该通过套接字顺序传输。换句话说,由于消息框架,一次只能在套接字本身上发送一个。TPL 数据流是否适合,或者我应该使用不同的排队模式?
- 我希望将消息序列化和消息传输之间的关注点完全分开。
我还没有看到很多使用这种策略的示例,只有“直接”套接字 I/O 或琐碎的实现。我的直觉告诉我,TPL Dataflow 非常适合,因为序列化和反序列化可以流水线化。
我不清楚如何将有效的无限链接收任务连接到 TPL 数据流或类似的东西。
有任何想法吗?