Event driven TCP Client
Solution 1
There's a relatively new project that essentially provides this: https://github.com/clariuslabs/reactivesockets
From their page:
Implements a very easy to use sockets API based on IObservable. It allows very simple protocol implementations such as:
var client = new ReactiveClient("127.0.0.1", 1055);
// The parsing of messages is done in a simple Rx query over the receiver observable
// Note this protocol has a fixed header part containing the payload message length
// And the message payload itself. Bytes are consumed from the client.Receiver
// automatically so its behavior is intuitive.
IObservable<string> messages = from header in client.Receiver.Buffer(4)
let length = BitConverter.ToInt32(header.ToArray(), 0)
let body = client.Receiver.Take(length)
select Encoding.UTF8.GetString(body.ToEnumerable().ToArray());
// Finally, we subscribe on a background thread to process messages when they are available
messages.SubscribeOn(TaskPoolScheduler.Default).Subscribe(message => Console.WriteLine(message));
client.ConnectAsync().Wait();
Solution 2
To get going in the right direction, check out Socket.BeginReceive()
and Socket.BeginSend()
.
Also, here is a handy series of examples from Microsoft for how to use the above functions. That helped me get started with those.
Unfortunately I cannot see an option to invoke the callback unless there are at least 35 bytes in the read buffer; it will get invoked whenever anything is received -- even if it's zero bytes. However, chances are that the counterparty will not be sending you messages byte by byte anyway.
Solution 3
I don't believe there is any event-based socket class available in the BCL, but if you're just looking for something a bit higher level than a bare Socket
, perhaps you should look into TcpClient
. It will handle buffering the underlying stream for you, letting you access it through a StreamReader
and the like:
TcpClient client;
// ... construct, connect, etc ...
new StreamReader(client.GetStream());
If you were using a line based protocol, you'd only need to use StreamReader.ReadLine()
, but StreamReader.Read()
should easily suit your purposes as well.
Chuck Bland
Started programming RSTS-E on a DEC PDP-11/70 in BASIC. Went from there to Cromemco, SOL, and other S-100 machines. Finally learned C in the DOS environment, then UNIX. Fast forward 20 years and I'm finally getting around to writing in the Windows environment. OOP is not a problem for me, but the details of Windows is indeed the most mental work for me.
Updated on July 09, 2022Comments
-
Chuck Bland almost 2 years
I want a event-driven, windows, c#, tcp client.
When there are at least 35 bytes in the read buffer, I want a handler to be called that will read those 35 bytes, grab a length value from that "packet", then do a blocking read for that second length of data.