问题描述
具体问题:在EndAccept执行时会产生10054错误.已经由try捕获,但EndAccept会阻塞线程,以下为部分代码privatevoidasyncAcceptCall(IAsyncResultar){Statusstatus=newStatus();SocketError_errorCode;try{//服务器的SocketSocketServerSocket=(Socket)ar.AsyncState;SocketClientSocket=ServerSocket.EndAccept(ar);//线程会在此处阻塞,当EndAccept报错时,阻塞时会影响其它客户端的接收.status.Client=ClientSocket;status.Buff=newbyte[4*1024];status.Ip=(IPEndPoint)ClientSocket.RemoteEndPoint;status.Client.BeginReceive(status.Buff,0,status.Buff.Length,SocketFlags.None,out_errorCode,newAsyncCallback(asynReceCall),status);}catch(SocketExceptionse){if(se.ErrorCode==10054){WriteException("网络连接异常");}}catch(Exceptione){WriteException("其它错误查看日志");}finally{mSocket.BeginAccept(newAsyncCallback(asyncAcceptCall),mSocket);}}
请问:1,在这个情况下为什么会出现10054错误,客户端为移动设备,采用的是GSM网络.2,阻塞时间为5-20秒,其间的连接处理会暂停,会对其它客户端有什么影响3,出现了10054错误,后续要如何操作.说明:客户端已经不可更改,只能在服务器处理.
解决方案
解决方案二:
1.不太清楚2.服务端应该有个监听线程吧,如果有一个socket申请就BeginAccept,在回调方法里,重新执行BeginAccept,然后再把传进来的异步操作状态转换为Listener,然后用这个Listener来EndAccept,这样就不会影响下一个socket连接申请。3.不太清楚。。。
解决方案三:
是这样,我采用的是Socket异步方式,主要问题是EndAccept引发的异常,10054错误.也就是当客户端断开时,EndAccept就阻塞住了,直到服务器发现Socket断开,引发异常,程序才继续执行.
解决方案四:
引用2楼sostonesi的回复:
是这样,我采用的是Socket异步方式,主要问题是EndAccept引发的异常,10054错误.也就是当客户端断开时,EndAccept就阻塞住了,直到服务器发现Socket断开,引发异常,程序才继续执行.
在服务端,你把listener设为全局变量。publicvoidbeginListener(){listener.BeginAcceptTcpClient(newAsyncCallback(DoAcceptCallback),listener);}publicvoidDoAcceptCallback(IAsyncResultar){try{beginListener();TcpListenerlistener=(TcpListener)ar.AsyncState;TcpClientclient=listener.EndAcceptTcpClient(ar);...}catch(Exceptione){//在抛出异常的时候做相应处理}}
这样每个连接请求相当于是独立的,就不会相互影响了。
解决方案五:
我认为在这里有个BUG正确的处理方式:Statusstatus=newStatus();SocketError_errorCode;try{//服务器的SocketSocketServerSocket=(Socket)ar.AsyncState;SocketClientSocket=ServerSocket.EndAccept(ar);//线程会在此处阻塞,当EndAccept报错时,阻塞时会影响其它客户端的接收.status.Client=ClientSocket;status.Buff=newbyte[4*1024];status.Ip=(IPEndPoint)ClientSocket.RemoteEndPoint;/*不要在这里重发,否则任务数会越来越多status.Client.BeginReceive(status.Buff,0,status.Buff.Length,SocketFlags.None,out_errorCode,newAsyncCallback(asynReceCall),status);*/}catch(SocketExceptionse){if(se.ErrorCode==10054){WriteException("网络连接异常");}}catch(Exceptione){WriteException("其它错误查看日志");}finally{//设置active标志,在程序退出前将active设为falseif(active){mSocket.BeginAccept(newAsyncCallback(asyncAcceptCall),mSocket);}}
但是,以上代码可能仍然存在问题,当.EndAccept抛出SocketException异常时,SocketClientSocket没有接收到返回值,因此我们无法获取到这个异常的Socket对象并将其关闭,所以会导致句柄泄露。EndAccept的SocketException10054错误会在客户端连接服务器成功后立即又关闭连接时发生。