【问题标题】:await for a response matching a request sequence number等待与请求序列号匹配的响应
【发布时间】:2012-08-09 23:53:19
【问题描述】:

我正在尝试实现一个网络应用协议客户端库,由 TCP 连接上的二进制请求/响应组成,我希望该客户端完全异步,依赖于 c#5 的 async/await 构造。

在 NetworkStream 上发送的每个请求都包含一个关联的应用序列号。对请求的响应必须指定相同的序列号,以便响应与原始请求匹配。 当我发出请求 R1 时,对 R1 的响应当然可以在将来的任何时间到来,而对其他请求的其他响应可能会在对 R1 的实际响应之前上线。

我想在库的客户端代码中做一些简单的愚蠢的事情

var resp = await SendSomeRequestAsync(req);

SendSomeRequestAsync 将在线上异步发送请求(正确处理该部分)并以某种方式等待相关响应(与请求中发送的序列号匹配),例如(在 SendSomeRequestAsync 中)

var dummy = await _ns.WriteAsync(rawBytes, 0, rawBytes.Length); // _ns is a NetworkStream
var resp = await GetResponseMatchingSequenceNumberAsync(sequenceNumber);

我有一个在客户端启动连接时启动的循环,它正在异步读取连接上的传入响应:

 while (true)
 {
    Response rsp = await ReadNextResponseAsync(_ns);
    DispatchReceivedResponse(rsp);
 }

我不知道如何实现 GetResponseMatchingSequenceNumberAsync,或者我已经完全错了。

希望我的问题足够清楚。

谢谢

【问题讨论】:

    标签: c# asynchronous async-await


    【解决方案1】:

    我确实遇到了这个问题,以下看起来很干净:

    创建一个IDictionary<int,Response> 并在其中存储TaskCompletionSource<Response> 实例。当您收到回复时,找到 TaskCompletionSource 并将其设置为已完成。我对这段代码的线程安全没有任何要求。字典应该是并发类型的,或者至少是在某种锁中访问的。

    public Task<Response> GetResponseMatchingSequenceNumberAsync(sequenceNumber)
    {
       var tcs=new TaskCompletionSource<Response>();
       pendingTasksDictionary.Add(sequenceNumber,tcs);
       return tcs.Task;
    }
    
    private void ResponseHandler(int sequenceNumber,Response response)
    {
       var pendingTcs=pendingTasksDictionary[sequenceNumber];
       //remove from dictionary
       pendingTcs.SetCompleted(response);
    }
    

    【讨论】:

    • 谢谢!这给了我一些工作和思考的东西;)
    猜你喜欢
    • 2014-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多