TcpListener超时/关于/某事?没有异步?

6
我创建了一个使用TcpListener的线程,当我的应用程序关闭时,我想终止该线程。我可以调用abort,但是由于TcpListener正在使用AcceptTcpClient阻塞,线程仍然存活。
是否有可能中止或设置超时或对AcceptTcpClient进行某些操作?如果没有办法永远停止它的阻塞,这种方法似乎没有任何用处。我的代码是串行的,我希望保持这种状态,因此是否有一种解决方案可以不使用BeginAcceptTcpClient,并编写异步代码?

1
另一个不应将阻塞套接字代码投入生产的原因是,异步套接字通信是唯一100%可靠的方法。 - Stephen Cleary
3个回答

17

简单的解决方案。待处理时进行检查。

while(!server.Pending())
{
    Thread.Sleep(10);
}
TcpClient client = server.AcceptTcpClient();

1
这是正确的吗?这不是超时。这是一种阻塞状态,只有在客户端连接时才会继续进行。server.AcceptTcpClient()也会等待客户端连接。如果没有客户端连接,它将保持等待循环。 - Sid133
@Sid133 - 这段代码可能会阻塞,但在检查是否存在挂起连接后,您没有使用块。您可以运行自己的线程来完成所有这些操作,并创建自己的超时机制。例如,您可以使用一个整数,在每次进入Thread.Sleep时递增。一旦它达到'n',离开循环,将TcpClient设置为“null”,并以失败状态结束该方法(例如异常)。 - Battle

4
你可以用Socket.Select()来替换AcceptTcpClient的调用,这个方法可以设置超时时间。
var sockl = new ArrayList { listener.Server };
Socket.Select(sockl, null, null, _timeout_);
if (sockl.Contains(listener.Server)) listener.AcceptTcpClient();

4

我使用AcceptTcpClient()在一个while(!Disposing)循环中接受我的客户端。
当我处置这个类时,我调用TcpListenerStop()函数并将Disposing设置为true;如下所示:

public class Server : IDisposable
{
    private TcpListener _tcpListener;
    private bool _isDisposing;

    public void Start()
    {
        (new Thread(new ThreadStart(ListenForClients))).Start();
    }

    private void ListenForClients()
    {
        this._tcpListener = new TcpListener(System.Net.IPAddress.Any, this.ListenPort);
        this._tcpListener.Start();

        while (!_isDisposing)
        {
            //blocks until a client has connected to the server
            TcpClient client = this._tcpListener.AcceptTcpClient();

            if (client == null) continue;

            //create a thread to handle communication with connected client
        }
    }

    public void Dispose()
    {
        this._isDisposing = true;
        this._tcpListener.Stop();
    }
}

请注意,这只是服务器类的一个小节选...
通过这种方式,程序可以始终锁定在 AcceptTcpClient() 函数上,而仍然可以结束。 然而,监听本身也必须在单独的线程上进行(使用 Start() 函数)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接