1

我有一个通过 TCP 运行的请求/响应协议,我想为其提供一个异步/等待 API。该协议是 STOMP,它是一个相当简单的基于文本的协议,通过 TCP 或 SSL 运行。在 STOMP 中,客户端发送六个左右的命令帧之一,并receipt在命令的标头中指定一个 ID。服务器将使用 aRECEIPTERRORframe 和receipt-id字段进行响应,因此客户端可以将响应与原始请求相匹配。服务器也可以随时发送一个MESSAGE帧(STOMP 本质上是一种消息传递协议),其中不包含receipt-id.

为了允许多个未完成的请求并处理任何MESSAGE帧,计划是始终有一个Socket.BeginReceive()未完成的请求。所以我在想的是,最简单的实现是创建一个可等待事件(如互斥锁),将该事件存储在一个表中,将带有receipt集合的命令请求发送到表中的索引,然后阻止该事件。触发时socket.BeginReceive(),该函数可以receipt-id从消息中获取,在表中查找事件,并发出信号(并存储一些状态,如成功或错误)。这将唤醒调用函数,该函数可以查看结果并将成功或失败返回给调用应用程序。

这听起来基本正确吗?我以前使用过 async/await API,但从未编写过自己的 API。如果可以,我应该使用哪种可等待事件?一个简单的Monitor.Wait()会阻塞但不是我想要的方式,对吗?如果我把整个东西都包起来,它的Task.Run()行为会正常Monitor.Wait()吗?或者是否有我应该使用的新同步结构?我基本上是在实施HttpClient.GetAsync(),有人知道这在幕后是如何工作的吗?

4

1 回答 1

2

HttpClient更简单,因为 HTTP 对每个请求只有一个响应。HTTP 中不存在未经请求的服务器消息。

要正确设置这样的事件“流”,最好使用TPL DataflowRx。否则,您必须创建一个无界接收缓冲区并重复异步 ReceiveMessage 调用。

因此,我建议使用 TPL 数据流管道来创建“消息”的源块,然后将一些与请求匹配(TaskCompletionSource用于通知发送者它已完成)并将其余的(MESSAGE帧)作为源块公开。

在内部,您的处理管道将如下所示:

  • 重复BeginReceive->
  • TransformBlock用于消息框架->
    • ActionBlock将响应消息与请求匹配。
    • BufferBlockMESSAGE框架。
于 2013-02-13T23:40:26.270 回答