gpt4 book ai didi

c# - 停止 TcpListener 的正确方法

转载 作者:IT王子 更新时间:2023-10-29 03:45:39 24 4
gpt4 key购买 nike

我目前正在使用 TcpListener 来处理传入的连接,每个连接都有一个线程来处理通信,然后关闭该单个连接。代码如下所示:

TcpListener listener = new TcpListener(IPAddress.Any, Port);
System.Console.WriteLine("Server Initialized, listening for incoming connections");
listener.Start();
while (listen)
{
// Step 0: Client connection
TcpClient client = listener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleConnection));
clientThread.Start(client.GetStream());
client.Close();
}

listen 变量是一个 bool 值,它是类中的一个字段。现在,当程序关闭时,我希望它停止监听客户端。将 listen 设置为 false 将阻止它接受更多连接,但由于 AcceptTcpClient 是一个阻塞调用,它至少会接受下一个客户端然后退出。有没有什么办法可以迫使它突然爆发并立即停止?在另一个阻塞调用运行时调用 listener.Stop() 有什么影响?

最佳答案

根据代码和我认为是您的设计,您可以使用这两个快速修复方法:

1。线程中止()

如果您已经从另一个线程启动了这个TcpListener 线程,您可以简单地对该线程调用Abort(),这将导致一个ThreadAbortException在阻塞调用中并在堆栈中向上移动。

2。 TcpListener.Pending()

第二个低成本修复是使用listener.Pending() 方法来实现轮询模型。然后,您可以使用 Thread.Sleep() 等待,然后再查看是否有新连接挂起。一旦你有一个挂起的连接,你调用 AcceptTcpClient() 并释放挂起的连接。代码看起来像这样:

while (listen) {
// Step 0: Client connection
if (!listener.Pending()) {
Thread.Sleep(500); // choose a number (in milliseconds) that makes sense
continue; // skip to next iteration of loop
}
TcpClient client = listener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleConnection));
clientThread.Start(client.GetStream());
client.Close();
}

异步重写

但是,您真的应该为您的应用程序采用非阻塞方法。在幕后,框架将使用重叠的 I/O 和 I/O 完成端口来实现异步调用的非阻塞 I/O。这也不是很难,只是需要以不同的方式思考您的代码。

基本上,您将使用 BeginAcceptTcpClient() 方法开始您的代码,并跟踪您返回的 IAsyncResult。您指向一个方法,该方法负责获取 TcpClient 并将其NOT 传递给新线程,而是传递给 ThreadPool.QueueUserWorkerItem ,所以你不会为每个客户端请求启动和关闭一个新线程(注意:如果你有特别长的请求,你可能需要使用你自己的线程池,因为线程池是共享的,如果你独占所有系统实现的应用程序的其他部分的线程可能会被饿死)。一旦监听器方法将新的 TcpClient 启动到它自己的 ThreadPool 请求,它会再次调用 BeginAcceptTcpClient() 并将委托(delegate)指向自身.

实际上,您只是将当前方法分解为 3 个不同的方法,然后这些方法将被不同的部分调用:

  1. 引导一切;
  2. 作为调用EndAcceptTcpClient()的目标,启动TcpClient到它自己的线程,然后再次调用它自己;
  3. 处理客户请求并在完成后关闭它。

(注意:您应该将 TcpClient 调用包含在 using(){} block 中以确保 TcpClient.Dispose ()TcpClient.Close() 方法即使在发生异常时也会被调用。或者,您可以将其放在 finally block 中 try {} finally {} block 。)

关于c# - 停止 TcpListener 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/365370/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com