'  /   .
                                                          ' /  .- .
                                                          .  .- .-
                                                        ./    .--...
                                              .-------- 0    .--
                                             /                 .......
                                            '                  ..
                                             '........            ----
                                                      .          --..
                                                       .   .---..   -
                                   分  o               .  '     -.
                                     分               /   '
                                                     / ' ' '
                                   \-分--/....... . '  ' '  '
                                    \ __/ -      - -'  '  ' '
                                                    '  '  ' '
                                     o              '   ' ' '
                                                    '   '  '
                                                     -..'.----------.
                                                        I   ----------
                                                 /////////.

解决方案 »

  1.   

    Socket.Select 方法
    确定一个或多个套接字的状态
    SocketException 访问 Socket 时发生操作系统错误。
      

  2.   

    Socket.Poll 方法
    public bool Poll(
       int microSeconds,
       SelectMode mode
    );
    microSeconds 
    等待响应的时间(以微秒为单位)。 
    mode 
    SelectMode 值之一。SelectRead  true,如果 Listen 已被调用且连接正处于挂起状态,而 Accept 将会成功 
    -或-true,如果数据可供读取-或-true,如果连接已被关闭、重置或终止;否则,返回 false。
     
    SelectWrite  true,如果正在处理 Connect 并且连接已成功 
    -或-true,如果数据已被发送;否则,返回 false。
     
    SelectError  true,如果正在处理不阻塞的 Connect 并且连接已失败 
    -或-true,如果 OutOfBandInline 未被设置且带外数据可用;否则,返回 false。
     
      

  3.   

    现在问题的关键是,我已经在上面的代码中加入了判断sock.connected属性
    出错在public void OnRecievedData( IAsyncResult ar )这个函数的int nBytesRec = sock.EndReceive( ar );
    可以看到出错的原因是"远程主机已经强制关闭了连接",我在出错之前加上
    if (sock.connected)
    这个判断,加上之后,错误的语句往后面跳了两行,变成了Invoke( m_AddMessage, new string [] { sRecieved } );
    这个语句,原因是"不能使用空值"
    真的是莫名其妙,而且可以设置断点看到这个时候的SOCK.CONNECTED属性为FALSE,也就是说不能执行到这个地方才对的
      

  4.   

    sock.connected的值true的情况下,不一定是连接状态
      

  5.   

    现在出错的时候sock.connected的值为false
      

  6.   

    获取 Socket 的连接状态。此属性将返回 Socket 的最新已知状态。当它返回 false 时,Socket 要么从未连接,要么将不再连接。当它返回 true 时,Socket 在最后一次 I/O 操作时连接。注意   即使 Connected 返回 true,Socket 也不一定仍处于 Connected 状态。
      

  7.   

    没遇到你说的情形.有可能异步状态导致调试时出现的情形.我想,你可以这样试一下:
    public void OnRecievedData( IAsyncResult ar )
    {
         Socket sock = ar.AsyncState as Socket;
         if( sock == null || !sock.Connected )
            return;
        try
        {
            ....
        }
        catch()
       {
         if( !sock.Connected )
         { yourFunc();}
       }
    或着在异常捕捉中,进一步处理.
      

  8.   

    我也碰到了楼主所说的这种问题,刚开始以为是真如异常信息所说的远程主机强制关闭链接,但trace过后才发现并不是这个问题,调用Connect()方法的时候并不会抛出异常,即便服务器没有响应也是如此,在这种情况下,向服务器发送数据后就会抛出远程主机强制关闭连接的异常。异常抛出后,应该马上终止异步调用,并关闭Socket链接。由于我的程序中同时有多个Socket在工作,所以我的做法是,将所有Socket添加到一个集合容器对象中,并启动一个Thread作为监视之用,定时遍历容器类中的Socket,并检查是否超时,若Socket超时,Close and Dispose it!
      

  9.   

    TO:fanchka(狼仔)
    谢谢,这样我已经试过了,我上面说过了,判断里面的那个RETURN根本就不会执行,继续往下的时候到INVOKE语句里面又抛出....
      

  10.   

    通常,服务器的异常关闭确实会导致客户端的Socket产生一个SocketExpception"远程主机已经强制关闭了连接",其实这个异常正是通知我们服务器异常关闭的操作,我们应该在程序里面捕捉这个异常,然后做出适当的处理,比如显示一段信息通知客户"服务器关闭了连接"之类的。
      

  11.   

    我有个问题:在关闭服务端socket的时候,总是出现:无法访问名为system.net.sockets.socket的已处置对象。
    创建一个项目,windows应用程序,放两个按钮,一个启动,一个停止:
    启动里面:
    IPEndPoint ipLocalEndPoint = new IPEndPoint(IPAddress.Parse("192.168.0.18"),1111);
    ListenSoc = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp );
    ListenSoc.Bind(ipLocalEndPoint);
    ListenSoc.Listen(5);
    ListenSoc.BeginAccept(new AsyncCallback(AcceptCallback),ListenSoc);
    停止按钮里面:
    try
    {
    ListenSoc.Shutdown(SocketShutdown.Both);
    ListenSoc.Close();
    if(ListenSoc.Connected) MessageBox.Show("无法关闭");
    }
    catch(Exception ex)
    {
    MessageBox.Show(ex.Message);
    }
    在家两个回掉函数:
    public static void AcceptCallback(IAsyncResult ar)
    {
    try
    {
    //connectDone.Set();
    byte[] bytes=new byte[1024];
    Socket listener=(Socket)ar.AsyncState;
    Socket handler=listener.EndAccept(ar);
    handler.BeginAccept(new AsyncCallback(AcceptCallback),handler);
    handler.BeginReceive(bytes,0,bytes.Length,0,new AsyncCallback(ReceiveCallback),handler);//handler.BeginReceive(state.buffer,0,StateObject.BufferSize,0,new AsyncCallback(ReadCallback),state);
    //receiveDone.WaitOne();
    }
    catch(Exception ex)
    {
    MessageBox.Show(ex.Message);
    } }
    public static void ReceiveCallback(IAsyncResult ar)
    {
    Socket aa=(Socket)ar.AsyncState;
    int bb=aa.EndReceive(ar);
    }
      

  12.   

    如果服务器端突然死机,客户端应该是无法知道服务器端状态的,我做了个测试,在socket建立后,把服务程序关闭,然后客户端第一次发送数据返回是成功,第二次发送才抛出异常。
    呵呵,至于怎么解决这个问题,自己程序想办法了。
      

  13.   

    如果服务端突然强制关闭掉客户端的远程连接,客户端怎么知道服务端已经关闭掉了SOCKET连接???---- try{  通讯   } catch(Exception e){  MessageBox.Show(...) }
    TCP是有连接的,如果服务器程序正常退出,底层tcp 会通知 client, 在 client 端会产生异常。用上面这段程序就行了如果服务器突然死机,或掉电, client 就无法从底层 tcp 及时得到消息,我的做法是 client 隔一段时间连接一次 server, 比如1秒,网络负担也不大。
      

  14.   

    获取 Socket 的连接状态。此属性将返回 Socket 的最新已知状态。当它返回 false 时,Socket 要么从未连接,要么将不再连接。当它返回 true 时,Socket 在最后一次 I/O 操作时连接。注意   即使 Connected 返回 true,Socket 也不一定仍处于 Connected 状态。Connected 返回上一次操作得到的状态。
    你不需要先知道是否连接再收发数据,你只需要直接收发数据,加上异常处理即可。
      

  15.   

    有没有通过socket协议来完成系统端口的映射啊???急求,,
    有的话, 能不能发一份代码给我,十分的感谢!!
    [email protected]