用thread开启线程和异步接收socket的疑问?
private Socket socket;
private Socket acceptSocket;
protected void Listen()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Any, 2000));
socket.Listen(0);
while (true)
{
//acceptSocket = socket.Accept();
//Thread thread = new Thread(new ThreadStart(BeginTempSocket));
//thread.Start();
//下面使用非阻塞式来接收客户端的请求,程序会有点卡,并且会报outofMemory的错误
socket.BeginAccept(new AsyncCallback(AsyncBeginTempSocket), socket);
}
}
protected void AsyncBeginTempSocket(IAsyncResult ar)
{
Socket s = (Socket)ar.AsyncState;
acceptSocket = s.EndAccept(ar);
............接收数据
}
protected void BeginTempSocket()
{
............接收数据
}
如上的代码:如果使用acceptSocket = socket.Accept();同步接收客户端,然后开启thread来接收数据,程序正常,很流畅;
但是如果使用socket.BeginAccept(new AsyncCallback(AsyncBeginTempSocket), socket);异步接收socket客户端的话,程序有点卡,并且连接了几次,就报outofMemory的错误了!具体的接收数据的代码都是一样的。
为什么呢?是不是异步的地方有哪里写得不对啊?
谢谢!
------解决方案--------------------BeginAccept很快就返回了。在循环中调用它,会造成很多很多很多个连接等待,不是好的选择。
由于OS会提供排队缓冲区,一般用一个线程进行Accept就可以了。连接后的具体通信再由不同的线程来处理(或进行异步操作)。
C# code
void Listen()
{
while (true)
{
Socket s = socket.Accept();
ThreadPool.QueueUserWorkItem(Worker, s);
}
}
void Worker(object state)
{
Socket soket = state as Socket;
//...
}
------解决方案--------------------
使用tcplistener和tcpclient会简单一些,而且可以使用到IOCP。
就算如你的代码那样使用sockey服务的主程序,大致(按照你的代码)就是这样:
C# code
protected void Listen()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Any, 2000));
socket.Listen(int.MaxValue);
socket.BeginAccept(new AsyncCallback(AsyncAcceptSocket), null);
}