none
如何使 Socket 和 NetworkSteram 判断远程主机断开且不崩溃 RRS feed

  • 问题

  • 虚心请教:

    程序背景使用 Socket ,采用 Tcp 方式连接主机。主机使用 Socket.Listen 方法在独立线程 BackgroundWorker 中监听,经过 Accept 应答后,创建网络流 NetworkStream,并另外新建独立线程 BackgroundWorker ,在新线程中,使用 While(true)循环接收数据,在循环内部使用 NetworkSteram.Read() 方法读取,并在 Read 的同时,用 Try...Cateh 捕捉 IOException 异常和 SocketException 异常。

    偶的问题是,在建立连接并开始读取后,基础 Socket 和 NetworkStream 如何正确的判断远程主机已经断开连接(正常断开或非正常关闭都要考虑),从而结束接收数据,并且不崩溃的退出。(前提是,我没有使用依靠协议的消息,没有自定义任何协议判断数据类型、发送命令类型,测试时,完全假设发送的是字符)。

    谢谢好心人儿
    不重要的其实最重要
    2009年7月28日 11:21

答案

  • 某次stream read得到0长度的byte[]  就可以判断正常断线
     
    答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。
    2009年7月29日 5:59
    版主

全部回复

  • 你好 根据msdn  你可以通过 Socket类的Connected 属性来判断

    Connected 属性获取截止到最后的 I/O 操作时 Socket 的连接状态。当它返回 false 时,表明 Socket 要么从未连接,要么已断开连接。

    Connected 属性的值反映最近操作时的连接状态。如果您需要确定连接的当前状态,请进行非阻止、零字节的 Send 调用。如果该调用成功返回或引发 WAEWOULDBLOCK 错误代码 (10035),则该套接字仍然处于连接状态;否则,该套接字不再处于连接状态。


    Wenn ich dich hab’,gibt es nichts, was unerträglich ist.坚持不懈!http://hi.baidu.com/1987raymond
    2009年7月29日 4:42
    版主
  • 某次stream read得到0长度的byte[]  就可以判断正常断线
     
    答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。
    2009年7月29日 5:59
    版主
  • 感谢两位版主的回复。

    1987raymond 兄,你的方法我在从 CodeProject 下载的一个例子上看到过,在那个程序里,Tcp 的服务器端是依靠这样的判断来判定的,我不知道我为什么使用 Socket.Connected 来判断就不行。

    我定义了 listenSocket(负责侦听)、acceptSocket(侦听到客户端连接,就是用此 Socket 来应答)、和 receiveStream(接收数据) 三个类变量来完成。简单的描述过程为:
    listenSocket.Bind();
    listenSocket.Listen();
    acceptSocket = listenSocket.Accept();
    ...
    receiverStream = new NetworkStream(this.acceptSocket);

    然后在单独的 backgroundWorker 线程中,使用 While(true) 不断地接收数据。在 While(true) 中,我就是不断地试验不同的判断方式,

    如果我用这个方式判断:
    while(true)
    {
       try
       {
          if(acceptSocket.Connected)
          { 显示接收到的信息 }
          else
          { 显示远程连接已断开,并 break 退出 while}

    奇怪的是,我断开客户端之后,这个while 循环并没有执行 else 中的部分,退出 while 循环,而是以极快的速度执行 if() 内的代码,不停地刷新我用来显示的 ListBox 造成程序的假死。而且没有触发任何异常。

    如果我将 if(acceptSocket.Connected) 换成去判断 listenSocket.Connected,那么在收到客户端的应答,开始执行接收部分也就是进入 whille 所在的方法后,立刻就执行了 else 中的代码,退出了。

    难道 ... listenSocket.Connected 属性为 false?刚应答了客户端,怎么会为 false 呢?而 accpetSocket.Connected 怎么又会一直是 true 呢?
    不重要的其实最重要
    2009年7月29日 12:26
  • 感谢两位版主

    韦恩卑鄙兄,我使用你的方法,用 int count = receiveStream.Read(),if(count >0) 的方法完成了我的目的。我想请教二位,如果说只有断开才会是 0 ,那么远程的主机不发送数据,是一个什么状态呢?阻塞么?导致一直停留在 count = receiveStream.Read() 这一句的位置?
    不重要的其实最重要
    2009年7月29日 12:30