gpt4 book ai didi

c# - TcpListener 排队连接的速度快于我清除它们的速度

转载 作者:太空狗 更新时间:2023-10-29 17:50:05 27 4
gpt4 key购买 nike

据我了解,TcpListener一旦您调用Start(),将对连接进行排队.每次调用AcceptTcpClient (或 BeginAcceptTcpClient ),它将从队列中取出一项。

如果我们加载测试 TcpListener通过一次向它发送 1,000 个连接,队列建立的速度远远超过我们清除它的速度,导致(最终)客户端超时,因为它没有得到响应,因为它的连接仍在队列中。然而,服务器似乎并没有承受太大压力,我们的应用程序没有消耗太多 CPU 时间,机器上其他受监控的资源也没有出汗。感觉我们现在的运行效率不够高。

我们正在调用 BeginAcceptTcpListener然后马上交给一个ThreadPool线程实际完成工作,然后调用 BeginAcceptTcpClient再次。所涉及的工作似乎并没有给机器带来任何压力,它基本上只是 3 秒的 sleep ,然后是字典查找,然后向 TcpClient 写入 100 字节。的流。

这是 TcpListener我们正在使用的代码:

    // Thread signal.
private static ManualResetEvent tcpClientConnected = new ManualResetEvent(false);

public void DoBeginAcceptTcpClient(TcpListener listener)
{
// Set the event to nonsignaled state.
tcpClientConnected.Reset();

listener.BeginAcceptTcpClient(
new AsyncCallback(DoAcceptTcpClientCallback),
listener);

// Wait for signal
tcpClientConnected.WaitOne();
}

public void DoAcceptTcpClientCallback(IAsyncResult ar)
{
// Get the listener that handles the client request, and the TcpClient
TcpListener listener = (TcpListener)ar.AsyncState;
TcpClient client = listener.EndAcceptTcpClient(ar);

if (inProduction)
ThreadPool.QueueUserWorkItem(state => HandleTcpRequest(client, serverCertificate)); // With SSL
else
ThreadPool.QueueUserWorkItem(state => HandleTcpRequest(client)); // Without SSL

// Signal the calling thread to continue.
tcpClientConnected.Set();
}

public void Start()
{
currentHandledRequests = 0;
tcpListener = new TcpListener(IPAddress.Any, 10000);
try
{
tcpListener.Start();

while (true)
DoBeginAcceptTcpClient(tcpListener);
}
catch (SocketException)
{
// The TcpListener is shutting down, exit gracefully
CheckBuffer();
return;
}
}

我假设答案与使用 Sockets 有关而不是 TcpListener , 或者至少使用 TcpListener.AcceptSocket ,但我想知道我们将如何去做?

我们的一个想法是调用 AcceptTcpClient并立即 Enqueue TcpClient成多个Queue<TcpClient>之一对象。这样,我们就可以在单独的线程(每个线程一个队列)上轮询这些队列,而不会遇到可能在等待其他线程时阻塞线程的监视器 Dequeue操作。然后每个队列线程都可以使用 ThreadPool.QueueUserWorkItemThreadPool 中完成工作线程,然后移动到出列下一个 TcpClient在它的队列中。您会推荐这种方法,还是我们正在使用的问题 TcpListener并且再多的快速出队也无法解决这个问题?

最佳答案

我编写了一些直接使用套接字的代码,但我缺乏对 1000 个客户端执行负载测试的方法。您能否尝试测试此代码与您当前的解决方案相比如何?我对结果非常感兴趣,因为我正在构建一个现在也需要接受大量连接的服务器。

static WaitCallback handleTcpRequest = new WaitCallback(HandleTcpRequest);

static void Main()
{
var e = new SocketAsyncEventArgs();
e.Completed += new EventHandler<SocketAsyncEventArgs>(e_Completed);

var socket = new Socket(
AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Loopback, 8181));
socket.Listen((int)SocketOptionName.MaxConnections);
socket.AcceptAsync(e);

Console.WriteLine("--ready--");
Console.ReadLine();
socket.Close();
}

static void e_Completed(object sender, SocketAsyncEventArgs e)
{
var socket = (Socket)sender;
ThreadPool.QueueUserWorkItem(handleTcpRequest, e.AcceptSocket);
e.AcceptSocket = null;
socket.AcceptAsync(e);
}

static void HandleTcpRequest(object state)
{
var socket = (Socket)state;
Thread.Sleep(100); // do work
socket.Close();
}

关于c# - TcpListener 排队连接的速度快于我清除它们的速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2745401/

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