正确的办法阻止的TcpListener [英] Proper way to stop TcpListener

查看:245
本文介绍了正确的办法阻止的TcpListener的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前使用的TcpListener来解决传入连接,其中每一个都给予了线程处理的通信,然后关闭了一个连接。 code如下所示:

I am currently using TcpListener to address incoming connections, each of which are given a thread for handling the communication and then shutdown that single connection. Code looks as follows:

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();
}

变量是一个布尔值,是在类的字段。现在,当程序关闭我希望它停止监听客户端。设置听将prevent它承担更多的连接,但由于 AcceptTcpClient 是一个阻塞调用,它会以最低的花费下一个客户端,然后退出。有没有什么办法,迫使它简单地爆发,停止,当时的权利呢?什么影响调用listener.Stop()有其他阻塞调用运行时?

The listen variable is a boolean that is a field on the class. Now, when the program shuts down I want it to stop listening for clients. Setting listen to false will prevent it from taking on more connections, but since AcceptTcpClient is a blocking call, it will at minimum take the next client and THEN exit. Is there any way to force it to simply break out and stop, right then and there? What effect does calling listener.Stop() have while the other blocking call is running?

推荐答案

有2建议,我会做给定code和我presume是你的设计。不过,我想首先指出,你应该使用类似网络或文件系统非阻塞I / O回调与我工作时/ O。这是迄今为止的 FAR 的更有效率,你的申请将工作好了很多,虽然他们很难程序。我将简要介绍在结束时提出的设计修改。

There are 2 suggestions I'd make given the code and what I presume is your design. However I'd like to point out first that you should really use non-blocking I/O callbacks when working with I/O like network or filesystems. It's far FAR more efficient and your application will work a lot better though they are harder to program. I'll briefly cover a suggested design modification at the end.


  1. 使用使用(){}为的TcpClient

  2. Thread.Abort的()

  3. TcpListener.Pending()

  4. 异步重写

使用使用(){}为TcpClient的

Use Using(){} for TcpClient

* 的注意,你应该附上TcpClient的通话中使用(){}块,确保TcpClient.Dispose()或TcpClient.Close()方法调用,即使在的情况下,一个例外。或者你可以把它放在一个try {}最后{}块。

* Note that you should really enclose your TcpClient call in a using(){} block to ensure that TcpClient.Dispose() or TcpClient.Close() methods are called even in the event of an exception. Alternately you can put this in the finally block of a try {} finally {} block.

Thread.Abort的()

Thread.Abort()

有2个东西我看你可以做。 1,如果你从另一个开始这个线程的TcpListener你可以简单的调用线程Thread.Abort的实例方法,这将导致一个ThreadAbortException到阻塞调用中被抛出,然后步行堆栈。

There are 2 things I see you could do. 1 is that if you have started this TcpListener thread from another you can simply call Thread.Abort instance method on the thread which will cause a threadabortexception to be thrown within the blocking call and walk up the stack.

TcpListener.Pending()

TcpListener.Pending()

第二个低成本的解决将是使用listener.Pending()方法来实现轮询模式。然后,您可以使用Thread.sleep代码,如果一个新的连接正在等待看到之前等待。一旦你有一个挂起的连接你会打电话来AcceptTcpClient,这会释放挂起的连接。在code会是这个样子。

The second low cost fix would be to use the listener.Pending() method to implement a polling model. You would then use a Thread.Sleep to "wait" before seeing if a new connection is pending. Once you have a pending connection you'd call AcceptTcpClient and that would release the pending connection. The code would look something like this.

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。这不是非常困难或者,它只是需要考虑你的code有点不同。

Finally I would recommend that you really move to a non-blocking methodology for your application. Under the covers the framework will use Overlapped I/O and I/O completion ports to implement non-blocking I/O from your asynchronous calls. It's not terribly difficult either, it just requires thinking about your code a little differently.

基本上你将与BeginAcceptTcpClient方法启动code和跟踪您返回的IAsyncResult的。你点,在其负责获取的TcpClient,并通过它关闭的的方法不的一个新的线程,但一个线程关闭ThreadPool.QueueUserWorkerItem,所以你不旋转起来,并关闭一个新的线程为每个客户端请求(请注意您可能需要使用自己的线程池,如果你是因为线程池的共享具有特别长寿命的要求,如果你垄断所有的线程由系统实现应用程序的其他部分可能会被饿死)。一旦监听方法已经启动了新的TcpClient以它自己的线程池请求再次呼吁BeginAcceptTcpClient和本身指向委托回​​来了。

Basically you would start your code with the BeginAcceptTcpClient method and keep track of the IAsyncResult that you are returned. You point that at a method whose responsible for getting the TcpClient and passing it off NOT to a new thread but to a thread off of the ThreadPool.QueueUserWorkerItem so you're not spinning up and closing a new thread for each client request (Note you may need to use your own thread pool if you have particularly long lived requests because the thread pool is shared and if you monopolize all the threads other parts of your application implemented by the system may be starved). Once the listener method has kicked off your new TcpClient to it's own ThreadPool request it calls BeginAcceptTcpClient again and points the delegate back at itself.

切实你刚分手当前的方法分为3个不同的方法,将得到再由各个部分调用。 1.引导一切,二是目标调用EndAcceptTcpClient,揭开序幕的TcpClient以它自己的线程,然后再调用自身3.处理客户请求和完成后关闭它。

Effectively you're just breaking up your current method into 3 different methods that will then get called by the various parts. 1. to bootstrap everything, 2. to be the target to call EndAcceptTcpClient, kick off the TcpClient to it's own thread and then call itself again, 3. to process the client request and close it when finished.

这篇关于正确的办法阻止的TcpListener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆