积极答复者
如何使 Socket 和 NetworkSteram 判断远程主机断开且不崩溃

问题
-
虚心请教:
程序背景使用 Socket ,采用 Tcp 方式连接主机。主机使用 Socket.Listen 方法在独立线程 BackgroundWorker 中监听,经过 Accept 应答后,创建网络流 NetworkStream,并另外新建独立线程 BackgroundWorker ,在新线程中,使用 While(true)循环接收数据,在循环内部使用 NetworkSteram.Read() 方法读取,并在 Read 的同时,用 Try...Cateh 捕捉 IOException 异常和 SocketException 异常。
偶的问题是,在建立连接并开始读取后,基础 Socket 和 NetworkStream 如何正确的判断远程主机已经断开连接(正常断开或非正常关闭都要考虑),从而结束接收数据,并且不崩溃的退出。(前提是,我没有使用依靠协议的消息,没有自定义任何协议判断数据类型、发送命令类型,测试时,完全假设发送的是字符)。
谢谢好心人儿
不重要的其实最重要- 已编辑 试试手气 2009年7月28日 11:23
答案
全部回复
-
你好 根据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 -
感谢两位版主的回复。
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 呢?
不重要的其实最重要