TCP 客户端 PCL - 如何从服务器发送和接收?
TCP Client PCL - How to send and receive from server?
我在这里使用这个库:sockets-for-pcl。
为什么要用这个库?
与 xamarin android 和 WPF 桌面进行通信。 (双向/双工通信)。
以下代码效果很好:
服务器:
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);
客户:
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();
我需要(双向/双工通信)的代码示例。
客户端向服务器发送数据,并从服务器接收数据。
看这个测试用例,再看方法TcpSocketClient_ShouldSendReceiveDataSimultaneously
:
此方法演示了双向通信。这有点令人困惑,因为它创建了 2 对连接,每个连接一个侦听器,因此它既充当客户端又充当服务器。您可以轻松地将其拆分为单独的客户端和服务器代码。
其实连接建立后,客户端和服务端本质上是一样的。两者都可以是倾听者。例如在推送通知场景中,客户端是监听器而不是服务器。
他们首先设置服务器套接字,因为服务器必须等待连接才能使客户端连接尝试成功:
listener = new TcpSocketListener();
var tcs = new TaskCompletionSource<ITcpSocketClient>();
await listener.StartListeningAsync(port);
listener.ConnectionReceived += (sender, args) => tcs.SetResult(args.SocketClient);
然后客户端尝试使用不同的套接字对象进行连接:
socket1 = new TcpSocketClient();
await socket1.ConnectAsync("127.0.0.1", port);
测试方法的设置方式有点混乱,因为它在一个方法中同时具有服务器和客户端套接字,但是启动双工 sending/receiving 的关键部分在这里,您可以看到两个套接字上都发生发送和接收。你可能不会以这种方式使用 WhenAll
,他们这样做只是为了完成他们的测试,但关键是你可以清楚地看到两个方向的 2 对 send/receive 结果:
// 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}")))
);
内部 sendAndReceive
是魔法发生的地方。请注意它在上面两次并行 运行,一次用于 socket1,一次用于 socket2。所以两个套接字都在同时发送和接收。在 sendAndReceive
中启动了两个任务,一个不断写入,一个不断读取(或接收)。所以你有两个 sendAndReceive 任务 运行 每个开始 2 个任务(一个读和一个写)。基本上并行发生 4 件事:Socket 1 读取、socket 1 写入、socket 2 读取、socket 2 写入。
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));
}
});
我在这里使用这个库:sockets-for-pcl。
为什么要用这个库?
与 xamarin android 和 WPF 桌面进行通信。 (双向/双工通信)。
以下代码效果很好:
服务器:
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);
客户:
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();
我需要(双向/双工通信)的代码示例。
客户端向服务器发送数据,并从服务器接收数据。
看这个测试用例,再看方法TcpSocketClient_ShouldSendReceiveDataSimultaneously
:
此方法演示了双向通信。这有点令人困惑,因为它创建了 2 对连接,每个连接一个侦听器,因此它既充当客户端又充当服务器。您可以轻松地将其拆分为单独的客户端和服务器代码。
其实连接建立后,客户端和服务端本质上是一样的。两者都可以是倾听者。例如在推送通知场景中,客户端是监听器而不是服务器。
他们首先设置服务器套接字,因为服务器必须等待连接才能使客户端连接尝试成功:
listener = new TcpSocketListener();
var tcs = new TaskCompletionSource<ITcpSocketClient>();
await listener.StartListeningAsync(port);
listener.ConnectionReceived += (sender, args) => tcs.SetResult(args.SocketClient);
然后客户端尝试使用不同的套接字对象进行连接:
socket1 = new TcpSocketClient();
await socket1.ConnectAsync("127.0.0.1", port);
测试方法的设置方式有点混乱,因为它在一个方法中同时具有服务器和客户端套接字,但是启动双工 sending/receiving 的关键部分在这里,您可以看到两个套接字上都发生发送和接收。你可能不会以这种方式使用 WhenAll
,他们这样做只是为了完成他们的测试,但关键是你可以清楚地看到两个方向的 2 对 send/receive 结果:
// 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}")))
);
内部 sendAndReceive
是魔法发生的地方。请注意它在上面两次并行 运行,一次用于 socket1,一次用于 socket2。所以两个套接字都在同时发送和接收。在 sendAndReceive
中启动了两个任务,一个不断写入,一个不断读取(或接收)。所以你有两个 sendAndReceive 任务 运行 每个开始 2 个任务(一个读和一个写)。基本上并行发生 4 件事:Socket 1 读取、socket 1 写入、socket 2 读取、socket 2 写入。
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));
}
});