.NET TcpSocket programming
本文关键字:programming TcpSocket NET | 更新日期: 2023-09-27 17:50:19
在。net的多连接环境中接受套接字的正确方法是什么?即使负载很高,下面这些是否足够?
while (true)
{
//block untill socket accepted
var socket = tcpListener.AcceptSocket();
DoStuff(socket) //e.g. spawn thread and read data
}
也就是说,我可以在单个线程中接受套接字,然后在线程/数据流/任何地方处理套接字吗?问题是关于accept部分
您可能需要BeginAccept异步操作而不是同步的Accept。
如果你想处理高负载,你肯定不希望每个连接一个线程-同样,你异步方法。
看看反应器或反应器模式,取决于你是否想要阻塞。我将推荐《并发和网络对象模式》这本书。
这应该没问题,但如果负载更高,你可能会考虑使用这个方法的异步版本:BeginAcceptSocket/EndAcceptSocket.
如果你想要性能最好的服务器,BeginAcceptSocket是一个更好的选择。
更重要的是,这些异步操作在底层使用线程池,而在你当前的实现中,你正在创建和销毁大量的线程,这是非常昂贵的。
我认为最好的方法是调用BeginAccept(),并在OnAccept中再次调用BeginAccept。这将为您提供最佳的并发性。
OnAccept应该像这样:
private void OnAccept(IAsyncResult ar)
{
bool beginAcceptCalled = false;
try
{
//start the listener again
_listener.BeginAcceptSocket(OnAccept, null);
beginAcceptCalled = true;
Socket socket = _listener.EndAcceptSocket(ar);
//do something with the socket..
}
catch (Exception ex)
{
if (!beginAcceptCalled)
{
//try listening to connections again
_listener.BeginAcceptSocket(OnAccept, null);
}
}
}
这与性能无关。重要的是你如何与每个客户沟通。此处理将比接受套接字消耗更多的CPU。
我将使用BeginAccept
/EndAccept
为监听套接字和 BeginReceive
/EndReceive
为客户端套接字。
由于我使用异步CTP和DataFlow,当前代码看起来像这样:
private async void WaitForSockets()
{
var socket = await tcpListener.AcceptSocketAsync();
WaitForSockets();
incomingSockets.Post(socket);
}
注意,看起来像递归调用不会导致堆栈溢出或阻塞。它将简单地为一个新的套接字启动一个新的awaiter并退出。