现在的位置: 首页 > 综合 > 正文

一个解决socket阻塞简单粗暴的方法

2017年11月27日 ⁄ 综合 ⁄ 共 1183字 ⁄ 字号 评论关闭

Socket编程的基础知识就不在这里多说了,可以参考:socket编程步骤

在一般的Socket中,为了通信的稳定性着想,会加入心跳的机制(参考:心跳机制),一旦客户端超过固定时间没有收到服务器的心跳回应,客户端会认为网络不通,此时需要断线重连

服务器为了支持客户端的断线重连,需要将serverSocket.accept方法放到循环里,如下:

while not self.__isStopped:# 线程结束标志
    connection,address=DTSSocket.accept()# 等待客户端连接,阻塞调用,会一直等待直到有新的连接进入才退出
    if len(self.__clientList):# 判断当前客户端列表
        for eachConnect in self.__clientList:
            if eachConnect[1][0] == address[0]:# 相同ip的客户端已经存在,则先删除之前的socket对象,在添加新的socket对象到客户端列表
                eachConnect[0].close()
                self.__Lock.acquire()
                self.__clientList.remove(eachConnect)
                self.__clientList.append((connection,address))
                self.__Lock.release()
            else:
                self.__Lock.acquire()
                self.__clientList.append((connection,address))
                self.__Lock.release()
            logger.info('DTS client ' + str(address) + ' connected')
DTSSocket.close()

当我结束上述线程的时候(比如在应用程序退出时应该释放所有的资源),问题就出现了,在其他地方(主线程的其他方法中)self.__isStopped的值为True,此时我们会想当然的认为上面的线程可以马上结束了,但是由于:

connection,address=DTSSocket.accept()# 等待客户端连接,阻塞调用,会一直等待直到有新的连接进入才退出

上面的线程会阻塞在accept直到有新的连接进来(只有在客户端接收不到心跳判定为网络连接异常时才回断线重连,如果心跳时间为30s,那至少得等30s,当用户点击退出之后还要等待整整30s,会是什么样的一个场景,可想而知),网上找了很多方法,单感觉太麻烦了,我的解决方法如下:

在设置self.__isStopped的值为True时,新建一个客户端socket并且连接上述等待客户端连接中的服务器,这样就可以简单的满足“有新的客户端连接到达”的要求,accept方法自然就会返回。单一定要记得关闭全部的socket对象哦(特别是最后用来解决服务器阻塞的socket)

抱歉!评论已关闭.