C# 如何设置 TcpListener 始终侦听和接受多个连接?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19387086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set up TcpListener to always listen and accept multiple connections?
提问by Kehlan Krumme
Here's my server app:
这是我的服务器应用程序:
public static void Main()
{
try
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
Console.WriteLine("Starting TCP listener...");
TcpListener listener = new TcpListener(ipAddress, 500);
listener.Start();
while (true)
{
Console.WriteLine("Server is listening on " + listener.LocalEndpoint);
Console.WriteLine("Waiting for a connection...");
Socket client = listener.AcceptSocket();
Console.WriteLine("Connection accepted.");
Console.WriteLine("Reading data...");
byte[] data = new byte[100];
int size = client.Receive(data);
Console.WriteLine("Recieved data: ");
for (int i = 0; i < size; i++)
Console.Write(Convert.ToChar(data[i]));
Console.WriteLine();
client.Close();
}
listener.Stop();
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
From what it looks like, it's already always listening while running, but I'm still asking that to specify that I'd like both always-listening and multiple connection support.
从它的外观来看,它已经在运行时一直在监听,但我仍然要求它指定我想要始终监听和多连接支持。
How can I modify this to constantly listen while also accepting multiple connections?
如何修改它以在接受多个连接的同时不断收听?
采纳答案by User 12345678
The socket on which you listen for incoming connections is commonly referred to as the listening socket. When the listening socket acknowledges an incoming connection, a socket commonly referred to as a child socketis created that effectively represents the remote endpoint.
用于侦听传入连接的套接字通常称为侦听套接字。当侦听套接字确认传入连接时,将创建一个通常称为子套接字的套接字,它有效地表示远程端点。
In order to handle multiple client connections simultaneously, you will need to spawn a new thread for each child socket on which the server will receive and handle data. Doing so will allow for the listening socket to accept and handle multiple connections as the thread on which you are listening will no longer be blocking or waiting while you wait for incoming data.
为了同时处理多个客户端连接,您需要为服务器将在其上接收和处理数据的每个子套接字生成一个新线程。这样做将允许侦听套接字接受和处理多个连接,因为在您等待传入数据时,您正在侦听的线程将不再阻塞或等待。
while (true)
{
Socket client = listener.AcceptSocket();
Console.WriteLine("Connection accepted.");
var childSocketThread = new Thread(() =>
{
byte[] data = new byte[100];
int size = client.Receive(data);
Console.WriteLine("Recieved data: ");
for (int i = 0; i < size; i++)
Console.Write(Convert.ToChar(data[i]));
Console.WriteLine();
client.Close();
});
childSocketThread.Start();
}
回答by unknown6656
I had a similar problem today, and solved it like this:
我今天遇到了类似的问题,解决方法如下:
while (listen) // <--- boolean flag to exit loop
{
if (listener.Pending())
{
Thread tmp_thread = new Thread(new ThreadStart(() =>
{
string msg = null;
TcpClient clt = listener.AcceptTcpClient();
using (NetworkStream ns = clt.GetStream())
using (StreamReader sr = new StreamReader(ns))
{
msg = sr.ReadToEnd();
}
Console.WriteLine("Received new message (" + msg.Length + " bytes):\n" + msg);
}
tmp_thread.Start();
}
else
{
Thread.Sleep(100); //<--- timeout
}
}
My loop did not get stuck on waiting for a connection and it did accept multiple connections.
我的循环没有卡在等待连接上,它确实接受了多个连接。
EDIT:The following code snippet is the async
-equivalent using Tasks instead of Threads. Please note that the code contains C#-8 constructs.
编辑:以下代码片段是async
使用任务而不是线程的等效项。请注意,代码包含 C#-8 结构。
private static TcpListener listener = .....;
private static bool listen = true; // <--- boolean flag to exit loop
private static async Task HandleClient(TcpClient clt)
{
using NetworkStream ns = clt.GetStream();
using StreamReader sr = new StreamReader(ns);
string msg = await sr.ReadToEndAsync();
Console.WriteLine($"Received new message ({msg.Length} bytes):\n{msg}");
}
public static async void Main()
{
while (listen)
if (listener.Pending())
await HandleClient(await listener.AcceptTcpClientAsync());
else
await Task.Delay(100); //<--- timeout
}