Reputation: 1805
I'm using this library here: sockets-for-pcl.
Why do you use this library?
To make communication with xamarin android and WPF desktop. (bidirectional / duplex communication).
The following code works great:
Server:
var listenPort = 11000;
var listener = new TcpSocketListener();
// when we get connections, read byte-by-byte from the socket's read stream
listener.ConnectionReceived += async (sender, args) =>
{
var client = args.SocketClient;
var bytesRead = -1;
var buf = new byte[1];
while (bytesRead != 0)
{
bytesRead = await args.SocketClient.ReadStream.ReadAsync(buf, 0, 1);
if (bytesRead > 0)
Debug.Write(buf[0]);
}
};
// bind to the listen port across all interfaces
await listener.StartListeningAsync(listenPort);
Client:
var address = "127.0.0.1";
var port = 11000;
var r = new Random();
var client = new TcpSocketClient();
await client.ConnectAsync(address, port);
// we're connected!
for (int i = 0; i<5; i++)
{
// write to the 'WriteStream' property of the socket client to send data
var nextByte = (byte) r.Next(0,254);
client.WriteStream.WriteByte(nextByte);
await client.WriteStream.FlushAsync();
// wait a little before sending the next bit of data
await Task.Delay(TimeSpan.FromMilliseconds(500));
}
await client.DisconnectAsync();
I need a code example for (bidirectional / duplex communication).
The client sends data to the server and receives the data from the server.
Upvotes: 0
Views: 854
Reputation: 38367
Look at this test case, and look at the method TcpSocketClient_ShouldSendReceiveDataSimultaneously
:
This method demonstrates bidirectional communication. It is a little confusing because it is creating 2 pairs of connections, a listener for each, so it is acting as both a client and server. You could easily split this out into separate client and server code.
In truth after the connection is established, client and server are essentially identical. Either can be the listener. In push notification scenarios for example, the client is the listener rather than server.
They setup the server socket first, because the server has to be waiting for a connection in order for a client connection attempt to succeed:
listener = new TcpSocketListener();
var tcs = new TaskCompletionSource<ITcpSocketClient>();
await listener.StartListeningAsync(port);
listener.ConnectionReceived += (sender, args) => tcs.SetResult(args.SocketClient);
Then the client attempt to connect using a different socket object:
socket1 = new TcpSocketClient();
await socket1.ConnectAsync("127.0.0.1", port);
It's a little confusing the way the test method is setup because it has both the server and client sockets in one method, but the key piece that kicks off the duplex sending/receiving is here, and you can see there's both sending and receiving occurring on both sockets. You probably wouldn't use WhenAll
in this way, they are doing it this way just to accomplish their testing, but the point is you can clearly see 2 pairs of send/receive results for both directions:
// let the sockets run for 2.5 seconds
var socketRunners =
Task.WhenAll(
Task.Run(() => sendAndReceive(socket1, sentToSocket2, recvdBySocket1, new CancellationTokenSource(TimeSpan.FromSeconds(2.5)).Token).ContinueWith(t=> Debug.WriteLine($"Socket 1 task completed: {t}"))),
Task.Run(() => sendAndReceive(socket2, sentToSocket1, recvdBySocket2, new CancellationTokenSource(TimeSpan.FromSeconds(2.5)).Token).ContinueWith(t => Debug.WriteLine($"Socket 2 task completed: {t}")))
);
Inside sendAndReceive
is where the magic is happening. Notice it is being run in parallel twice above, once for socket1, and once for socket2. So both sockets are sending and receiving at the same time. Inside sendAndReceive
two tasks are started, one that is constantly writing, and one that is constantly reading(or receiving). So you have two sendAndReceive tasks running with each starting 2 tasks(a read and a write). Essentially 4 things happening in parallel: Socket 1 reading, socket 1 writing, socket 2 reading, socket 2 writing.
var send = Task.Run(async () =>
{
var buf = new byte[1000];
while (!token.IsCancellationRequested)
{
r.NextBytes(buf);
sent.AddRange(buf);
await socket.WriteStream.WriteAsync(buf, 0, buf.Length, token);
await socket.WriteStream.FlushAsync(token);
}
});
var recv = Task.Run(async () =>
{
var buf = new byte[1000];
while (!token.IsCancellationRequested)
{
var len = await socket.ReadStream.ReadAsync(buf, 0, buf.Length, token);
recvd.AddRange(buf.Take(len));
}
});
Upvotes: 1