.net 套接字处理在几个并发请求之后变得同步

.net 套接字处理在几个并发请求之后变得同步,.net,sockets,asynchronous,tcplistener,.net,Sockets,Asynchronous,Tcplistener,我们有一个TCP服务器,它接受多个请求,并用一个单独的线程处理每个请求。最近我们收到了性能下降的报告,其原因似乎是请求被连续处理 具体来说,实例化TcpListener并调用TcpListener.BeginAcceptSocket()的线程与执行回调方法的线程相同 private void ListenForConnections() { TcpListener listener = new TcpListener(IPAddress.Any, args.port); list

我们有一个TCP服务器,它接受多个请求,并用一个单独的线程处理每个请求。最近我们收到了性能下降的报告,其原因似乎是请求被连续处理

具体来说,实例化TcpListener并调用TcpListener.BeginAcceptSocket()的线程与执行回调方法的线程相同

private void ListenForConnections()
{
    TcpListener listener = new TcpListener(IPAddress.Any, args.port);
    listener.Start();

    log.DebugFormat("Listener started on thread {0}", Thread.CurrentThread.ManagedThreadId);

    while (true)
    {
        _accepted.Reset();

        IAsyncResult asyncResult = listener.BeginAcceptSocket(
            new AsyncCallback(AcceptConnection), listener);

        _accepted.WaitOne();
    }
}

private void AcceptConnection(IAsyncResult ar)
{
    TcpListener listen = ar.AsyncState as TcpListener;
    if (listen == null) throw new Exception("no listener?");

    log.DebugFormat("Accepted connection on thread {0}", Thread.CurrentThread.ManagedThreadId);

    using (Socket socket = listen.EndAcceptSocket(ar))
    {
        _accepted.Set();

        DoWork(socket);
    }
}
如果一个客户端程序的多个实例同时执行,并且每个实例在一个循环中向服务器执行一个请求,从而创建多个并发连接,则日志可能如下所示:

16:49:08.954 [1] DEBUG SocketAsyncServer.Program.ListenForConnections Listener started on thread 1
16:49:18.639 [4] DEBUG SocketAsyncServer.Program.AcceptConnection Accepted connection on thread 4
16:49:18.648 [6] DEBUG SocketAsyncServer.Program.AcceptConnection Accepted connection on thread 6
16:49:18.650 [1] DEBUG SocketAsyncServer.Program.AcceptConnection Accepted connection on thread 1
16:49:21.671 [1] DEBUG SocketAsyncServer.Program.AcceptConnection Accepted connection on thread 1
16:49:24.673 [1] DEBUG SocketAsyncServer.Program.AcceptConnection Accepted connection on thread 1
16:49:27.676 [1] DEBUG SocketAsyncServer.Program.AcceptConnection Accepted connection on thread 1
请注意,DoWork()方法会休眠3秒,说明只有开始线程执行回调方法时,日志时间戳中的3秒节奏

private void ListenForConnections()
{
    TcpListener listener = new TcpListener(IPAddress.Any, args.port);
    listener.Start();

    log.DebugFormat("Listener started on thread {0}", Thread.CurrentThread.ManagedThreadId);

    while (true)
    {
        _accepted.Reset();

        IAsyncResult asyncResult = listener.BeginAcceptSocket(
            new AsyncCallback(AcceptConnection), listener);

        _accepted.WaitOne();
    }
}

private void AcceptConnection(IAsyncResult ar)
{
    TcpListener listen = ar.AsyncState as TcpListener;
    if (listen == null) throw new Exception("no listener?");

    log.DebugFormat("Accepted connection on thread {0}", Thread.CurrentThread.ManagedThreadId);

    using (Socket socket = listen.EndAcceptSocket(ar))
    {
        _accepted.Set();

        DoWork(socket);
    }
}
我已经看到许多例子使用相同的模式通过线程处理传入的请求,但是没有描述我们正在看到的情况


如果您有任何帮助,我们将不胜感激。

您在这里使用了多少并发套接字?如果它是一把,你可能会没事(虽然它并不漂亮);如果它是数百个,或者是一个大容量的TCP服务器(数千个、数万个,等等),那么:这是一个糟糕的设计——它是每个套接字的线程,根本不起作用。一旦你的线程池饱和,你就死定了。此外,它在这之前也很糟糕(每个套接字都有一个完整的线程加堆栈,非常庞大)。再说一遍:你在处理多少个套接字?@marc gravell:在最坏的情况下,我们会看到10个并发连接。上面的示例是使用5个进程/连接创建的。谢谢你的回复。(呵呵,我在那里评论了一下错误的问题;删除)