如何判断socket的连接状态?

时间:2020-12-29 17:24:18
服务器端是用多线程,客户端已经断开的连接就需要销毁。在服务器端用socket.connected无法判断客户端是否已经断开,使用select和pool也无法判断出来,怎么回事?一般采取什么方法判断,然后销毁?

6 个解决方案

#1


不太好判断

#2


模仿三次握手的方式。

#3


那么通常是怎么做的?如果客户端经常断开,服务器的资源一直得不到释放怎么可以呢?

#4


mark

#5


客户端断开有两种情况,一种是通讯故障或者对方失去响应导致超时,一种是对方关闭了连接,主动断开。超时这种情况,是无法判断的。因为超时之前无法知道这个连接是否还可以继续使用。
我们希望判断的是对方主动关闭连接的情况。
                private bool IsCanRead(Socket sock) {
            try {
                //检查socket的状态是否可读
                if (sock.Connected && sock.Poll(0, SelectMode.SelectRead)) {
                    byte[] bytes = new byte[1];
                    //因为TCP/IP协议无法精确的判断网络是否可用
                    //试读一个字符,Peek参数指定读取的字符不会从缓冲区中移除
                    //假如可读则表示连接可用
                    if (sock.Receive(bytes, 0, 1, SocketFlags.Peek) != 0) {
                        return true;
                    }
                    //Close("Disconnected.");
                    else {
                        return false;
                    }
                }
                else {
                    return true;
                }
            }
            catch (SocketException e) {
                if(e.SocketErrorCode==SocketError.ConnectionReset){
                    return false;
                }

                throw e;
            }
        }
这段代码还存在一定问题,对方断开时,如果缓冲区还存有未读出的字节的话,会返回true。所以还要结合socket.Availiable来判断。只有在socket.Availiable=0时,执行这段代码,才能判断socket是否被对方断开。

#6


楼主的设计有问题,如果是Threaded模式的服务器,应当用线程池来代替,关于线程池的描述参考一下msdn, 不过出于对性能的考虑,还是建议你使用IO异步的模式。

#1


不太好判断

#2


模仿三次握手的方式。

#3


那么通常是怎么做的?如果客户端经常断开,服务器的资源一直得不到释放怎么可以呢?

#4


mark

#5


客户端断开有两种情况,一种是通讯故障或者对方失去响应导致超时,一种是对方关闭了连接,主动断开。超时这种情况,是无法判断的。因为超时之前无法知道这个连接是否还可以继续使用。
我们希望判断的是对方主动关闭连接的情况。
                private bool IsCanRead(Socket sock) {
            try {
                //检查socket的状态是否可读
                if (sock.Connected && sock.Poll(0, SelectMode.SelectRead)) {
                    byte[] bytes = new byte[1];
                    //因为TCP/IP协议无法精确的判断网络是否可用
                    //试读一个字符,Peek参数指定读取的字符不会从缓冲区中移除
                    //假如可读则表示连接可用
                    if (sock.Receive(bytes, 0, 1, SocketFlags.Peek) != 0) {
                        return true;
                    }
                    //Close("Disconnected.");
                    else {
                        return false;
                    }
                }
                else {
                    return true;
                }
            }
            catch (SocketException e) {
                if(e.SocketErrorCode==SocketError.ConnectionReset){
                    return false;
                }

                throw e;
            }
        }
这段代码还存在一定问题,对方断开时,如果缓冲区还存有未读出的字节的话,会返回true。所以还要结合socket.Availiable来判断。只有在socket.Availiable=0时,执行这段代码,才能判断socket是否被对方断开。

#6


楼主的设计有问题,如果是Threaded模式的服务器,应当用线程池来代替,关于线程池的描述参考一下msdn, 不过出于对性能的考虑,还是建议你使用IO异步的模式。