TCP聊天服务器套接字v1.3
在长连接下,可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。这个时候,就可以使用心跳包,来维持长连接以及保活
心跳机制就是每隔时间发送一个固定信息给服务端,服务端收到后回复一个固定信息如果服务端几分钟内没有收到客户端信息则视客户端断开。发包方可以是客户也可以是服务端,具体看哪边实现更方便合理
由应用程序自己发送心跳包来检测连接是否正常,服务器每隔一定时间向客户端发送一个短小的数据包,然后启动一个线程,在线程中不断检测客户端的回应, 如果在一定时间内没有收到客户端的回应,即认为客户端已经掉线;同样,如果客户端在一定时间内没有收到服务器的心跳包,则认为连接不可用
将关闭的用户端关闭,释放服务器内存
所有版本记录:
v1.0
: TCP聊天服务器套接字|PyQt5+socket(TCP端口映射+端口放行)+logging+Thread(含日志,html)+anaconda打包32位exe(3.4万字)|python高阶v1.1
: python TCP套接字服务器v1.1-新增服务端命令功能及修改bug(socket+PyQt5)v1.2
: python TCP服务器v1.2 - 服务端新增用户登录注册(json, md5加密)
昨天,我编写了一个连续攻击的程序,以我的电脑, 抗压结果如下(单位: 线程):
服务器 | 客户端(PyQt5) |
---|---|
26 | 26 |
优化完后:
服务端 | 客户端(PyQt5) |
---|---|
167 | 27 |
不要问我一共坚持了多少分钟,因为我攻击的程序在释放内存的情况下也已经崩溃了…
服务器 | 客户端(PyQt5) |
---|---|
517 | 517 |
优化完后:
服务端 | 客户端(PyQt5) |
---|---|
1000+ | ~ |
很显然, 服务器删除关闭套接字也是必不可少的.
class Server(object):
def __init__(..., clear_time=20):
...
self.clear_time = clear_time
def clear_socket(self):
while True:
del_list = list(filter(lambda c: hasattr(c, 'Quitted') or (not c.isOpen()), self.connect))
for user in del_list:
self.connect.remove(user)
if del_list:
logger.info(f"Clear the closed client socket, number is {len(del_list)}.")
else:
logger.info('None of the sockets have been cleaned.')
time.sleep(self.clear_time)
def run(self):
...
logger.info(f'Clear the closed socket once every {self.clear_time} second(s).')
threading(True, target = self.clear_socket)
...
class Client(object):
def quit(self) -> None:
if hasattr(self, 'Quitted'):
return
else:
self.Quitted = True
if self.isOpen() is True:
self.socket.close()
self.server.quit(self.username,self.addr)