我正在编写一个P2P程序,该程序必须在多个实例之间发送和接收数据。 当我创建单独的线程来侦听infinity while循环中的传入数据时,我遇到了一个问题,但是我只收到第一条消息,然后什么也没有。 我究竟做错了什么? 代码:
Task t = new Task(() => {
try {
server = new TcpListener(IPAddress.Parse(STD_IP), STD_PORT);
server.Start();
odjemalec = server.AcceptTcpClient();
nwStream = odjemalec.GetStream();
}
catch (Exception ex) {
Console.WriteLine("Error\n" + ex.Message + "\n" + ex.StackTrace);
}
while(true) {
listen();
}
});
t.Start();
答案 0 :(得分:0)
如果要使用任务(我强烈建议使用这种方法),则每个传入连接都需要监听器任务和 TcpClient Responder任务。
这是基本的TCP侦听器任务
static async Task StartTcpServerAsync()
{
var tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, 9999));
tcpListener.Start();
while (true)
{
var tcpClient = await tcpListener.AcceptTcpClientAsync();
_ = StartTcpClientAsync(tcpClient);
}
}
我们启动TcpListener
并开始监听连接。每次建立连接时,我们都会将关联的TcpClient
交给新的Task。
这是服务器端TCP客户端任务-它位于服务器上,由侦听器启动
static async Task StartTcpClientAsync(TcpClient tcpClient)
{
Console.WriteLine($"Connection from: [{tcpClient.Client.RemoteEndPoint}]");
var stream = tcpClient.GetStream();
var buffer = new byte[1024];
while (true)
{
int x = await stream.ReadAsync(buffer, 0, 1024);
Console.WriteLine($"[{tcpClient.Client.RemoteEndPoint}] _ " +
$"read {x} bytes {System.Text.Encoding.UTF8.GetString(buffer)}");
}
}
在此示例中,我们只写出接收到的字节。
最后
为了完整起见,这里有一个Main也是一个TCPSender-通常,Sender将位于完全不同的计算机上,但是为了展示Tasks的强大功能,我们将在同一过程中运行它。
static async Task Main(string[] args)
{
_ = StartTcpServerAsync();
await Task.Delay(2000);
await RunSenderAsync();
}
static async Task RunSenderAsync()
{
var tcpClient = new TcpClient("127.0.0.1", 9999);
var s = tcpClient.GetStream();
tcpClient.NoDelay = true;
for (var i = 65; i < 91; i++)
{
s.Write(BitConverter.GetBytes(i), 0, 1);
await Task.Delay(1000);
}
}
我发现很多人感到困惑的地方是,对于每个收到的连接,服务器上都需要一个TcpClient。
答案 1 :(得分:0)
这个答案是给塞尔文的。
我将Main更改为运行三个RunSenderAsync
客户端。
这是控制台窗口中的输出。如您所见,三个客户端连接到侦听器,该侦听器随后启动三个任务,每个任务将在WorkerThread池的Worker线程上运行。我已经更新了Writeline()
以打印线程ID,以便您可以看到任务在WorkerThreads周围移动。
BiDi source: [127.0.0.1:50279] connected to Pipeline Server
Connection from: [127.0.0.1:50279]
BiDi source: [127.0.0.1:50280] connected to Pipeline Server
BiDi source: [127.0.0.1:50281] connected to Pipeline Server
Connection from: [127.0.0.1:50280]
[127.0.0.1:50280] read 1 bytes A
^^ On Thread ID: 7
[127.0.0.1:50279] read 1 bytes A
^^ On Thread ID: 6
Connection from: [127.0.0.1:50281]
[127.0.0.1:50281] read 1 bytes A
^^ On Thread ID: 5
[127.0.0.1:50280] read 1 bytes B
^^ On Thread ID: 7
[127.0.0.1:50279] read 1 bytes B
^^ On Thread ID: 8
[127.0.0.1:50281] read 1 bytes B
^^ On Thread ID: 5
[127.0.0.1:50279] read 1 bytes C
^^ On Thread ID: 6
[127.0.0.1:50281] read 1 bytes C
^^ On Thread ID: 5
[127.0.0.1:50280] read 1 bytes C
^^ On Thread ID: 7
[127.0.0.1:50280] read 1 bytes D
^^ On Thread ID: 5
[127.0.0.1:50279] read 1 bytes D
^^ On Thread ID: 7
[127.0.0.1:50281] read 1 bytes D
^^ On Thread ID: 8
[127.0.0.1:50280] read 1 bytes E
^^ On Thread ID: 5
[127.0.0.1:50281] read 1 bytes E
^^ On Thread ID: 7
[127.0.0.1:50279] read 1 bytes E
^^ On Thread ID: 8
[127.0.0.1:50280] read 0 bytes E
这是完整的源代码:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace ReadAsync
{
class Program
{
static async Task StartTcpClientAsync(TcpClient tcpClient)
{
Console.WriteLine($" Connection from: [{tcpClient.Client.RemoteEndPoint}]");
var stream = tcpClient.GetStream();
var buffer = new byte[1024];
while (true)
{
int x = await stream.ReadAsync(buffer, 0, 1024);
Console.WriteLine($" [{tcpClient.Client.RemoteEndPoint}] " +
$"read {x} bytes {System.Text.Encoding.UTF8.GetString(buffer)} "+
$" ^^ On Thread ID: {Thread.CurrentThread.ManagedThreadId}");
}
}
static async Task StartTcpServerAsync()
{
var tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, 9999));
tcpListener.Start();
while (true)
{
var tcpClient = await tcpListener.AcceptTcpClientAsync();
_ = StartTcpClientAsync(tcpClient);
}
}
static async Task Main(string[] args)
{
_ = StartTcpServerAsync();
await Task.Delay(2000);
_ = RunSenderAsync();
_ = RunSenderAsync();
await RunSenderAsync();
}
static async Task RunSenderAsync()
{
using var tcpClient = new TcpClient("127.0.0.1", 9999);
Console.WriteLine($" BiDi source: [{tcpClient.Client.LocalEndPoint}] connected to Pipeline Server");
using var s = tcpClient.GetStream();
tcpClient.NoDelay = true;
for (var i = 65; i < 70; i++)
{
s.Write(BitConverter.GetBytes(i), 0, 1);
await Task.Delay(1000);
}
}
}
}