EndAccept异常引发的问题

sostonesi 2013-12-17 11:52:30
具体问题: 在EndAccept执行时会产生 10054错误.已经由try捕获,但EndAccept会阻塞线程,以下为部分代码

private void asyncAcceptCall(IAsyncResult ar)
{
Status status = new Status();
SocketError _errorCode;
try
{
//服务器的Socket
Socket ServerSocket = (Socket)ar.AsyncState;

Socket ClientSocket = ServerSocket.EndAccept(ar);
//线程会在此处阻塞,当EndAccept报错时,阻塞时会影响其它客户端的接收.
status.Client = ClientSocket;
status.Buff = new byte[4 * 1024];
status.Ip = (IPEndPoint)ClientSocket.RemoteEndPoint;
status.Client.BeginReceive(status.Buff, 0,
status.Buff.Length,
SocketFlags.None,
out _errorCode,
new AsyncCallback(asynReceCall),
status);
}
catch (SocketException se)
{
if (se.ErrorCode == 10054)
{
WriteException("网络连接异常");
}
}
catch (Exception e)
{
WriteException("其它错误 查看日志");
}
finally
{
mSocket.BeginAccept(new AsyncCallback(asyncAcceptCall), mSocket);
}
}

请问:
1,在这个情况下为什么会出现10054错误,客户端为移动设备,采用的是GSM网络.
2,阻塞时间为5-20秒,其间的连接处理会暂停,会对其它客户端有什么影响
3,出现了10054错误,后续要如何操作.

说明:
客户端已经不可更改,只能在服务器处理.
...全文
238 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
AutoWalk 2015-12-14
  • 打赏
  • 举报
回复
我认为在这里有个BUG 正确的处理方式:

Status status = new Status();
    SocketError _errorCode;
    try
    {
        //服务器的Socket
        Socket ServerSocket = (Socket)ar.AsyncState;
 
        Socket ClientSocket = ServerSocket.EndAccept(ar);
        //线程会在此处阻塞,当EndAccept报错时,阻塞时会影响其它客户端的接收.
        status.Client = ClientSocket;
        status.Buff = new byte[4 * 1024];
        status.Ip = (IPEndPoint)ClientSocket.RemoteEndPoint;
/*不要在这里重发,否则任务数会越来越多
        status.Client.BeginReceive(status.Buff, 0, 
                                   status.Buff.Length, 
                                   SocketFlags.None, 
                                   out _errorCode, 
                                   new AsyncCallback(asynReceCall), 
                                   status);
*/
    }
    catch (SocketException se)
        {
        if (se.ErrorCode == 10054)
        {
            WriteException("网络连接异常");
        }
    }
    catch (Exception e)
    {
        WriteException("其它错误 查看日志");
    }
    finally
    {
      //设置active标志,在程序退出前将active设为false
      if(active){
        mSocket.BeginAccept(new AsyncCallback(asyncAcceptCall), mSocket);
     }
    }
但是,以上代码可能仍然存在问题,当.EndAccept抛出SocketException异常时,Socket ClientSocket没有接收到返回值,因此我们无法获取到这个异常的Socket对象并将其关闭,所以会导致句柄泄露。 EndAccept的SocketException 10054错误会在客户端连接服务器成功后立即又关闭连接时发生。
  • 打赏
  • 举报
回复
引用 2 楼 sostonesi 的回复:
是这样,我采用的是Socket异步方式,主要问题是EndAccept引发的异常,10054错误.也就是当客户端断开时,EndAccept就阻塞住了,直到服务器发现Socket断开 ,引发异常,程序才继续执行.
在服务端,你把listener设为全局变量。

public void beginListener()
        {
            listener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptCallback), listener);
        }
public void DoAcceptCallback(IAsyncResult ar)
        {
            try
            {
                beginListener();
                TcpListener listener = (TcpListener)ar.AsyncState;
                TcpClient client = listener.EndAcceptTcpClient(ar);
                ...
            }
            catch(Exception e)
            {
                //在抛出异常的时候做相应处理
            }
        }
这样每个连接请求相当于是独立的,就不会相互影响了。
sostonesi 2013-12-17
  • 打赏
  • 举报
回复
是这样,我采用的是Socket异步方式,主要问题是EndAccept引发的异常,10054错误.也就是当客户端断开时,EndAccept就阻塞住了,直到服务器发现Socket断开 ,引发异常,程序才继续执行.
  • 打赏
  • 举报
回复
1.不太清楚 2.服务端应该有个监听线程吧,如果有一个socket申请就BeginAccept,在回调方法里,重新执行BeginAccept,然后再把传进来的异步操作状态转换为Listener,然后用这个Listener来EndAccept,这样就不会影响下一个socket连接申请。 3.不太清楚。。。

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧