I am trying to implement a network applicative protocol client library, composed of binary request/responses over TCP connection, and I would like this client to be fully asynchronous relying on async/await constructs of c#5.
Each request sent on the NetworkStream contains an associated applicative sequence number. The reponse made to the request, must specify the same sequence number so that response can be matched with original request.
When I issue a request R1, response to R1 can of course come at any time in the future, and other responses for other requests may come on the line before the actual response to R1.
What I would like to do in the client code of the library is something as simple stupid as
var resp = await SendSomeRequestAsync(req);
SendSomeRequestAsync will send the request asynchronously on the line (got that part right) and somehow await the associated response (matching the sequence number that was sent in the request), such as (in SendSomeRequestAsync)
var dummy = await _ns.WriteAsync(rawBytes, 0, rawBytes.Length); // _ns is a NetworkStream
var resp = await GetResponseMatchingSequenceNumberAsync(sequenceNumber);
I have a loop that is launched when client start connection which is reading incoming responses on the connection asynchronously :
while (true)
{
Response rsp = await ReadNextResponseAsync(_ns);
DispatchReceivedResponse(rsp);
}
I can’t figure out how to implement the GetResponseMatchingSequenceNumberAsync, or if I am already doing it totally wrong.
Hope my question is clear enough.
Thanks
I’ve run into exactly this issue, and the following seemed pretty clean:
Create an
IDictionary<int,Response>and storeTaskCompletionSource<Response>instances in it. When you get a response back, find the TaskCompletionSource and set it completed. I make no claims for the thread safety of this code. The dictionary should probably be of the concurrent kind, or at least accessed in a lock of some sort.