当前位置: 首页 > 后端技术 > Python

用 Python 写网络编程(四)

时间:2023-03-26 17:36:37 Python

为了模拟fd_port自增1,相当于很多clients连接进来,这里如果对Threading不熟悉,需要自己稍微学习一下。importsocketimportjsonfromthreadingimportThreadimportastclassHeartBeatServer:def__init__(self,addr:tuple,max:int):self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)self.sock.setsockopt(socket.SOL_SOCKET,套接字.SO_REUSEADDR,1)self.sock.bind(addr)#支持的最大连接数self.sock.listen(max)self.user=[]defencode_buffer(self,conn:socket.socket,data:strorbytesordict):"""发送数据:paramconn:客户端链接到服务器的句柄:paramdata:data:return:"""ifisinstance(data,str):data=data.encode("utf-8")elifisinstance(data,dict):data=str(data).encode("utf-8")conn.send(str(data).encode("utf-8"))defmatch_data(self,recv)->bool:"""匹配反序列化数据:paramrecv::return:"""ifisinstance(recv,dict):returnrecv.get("ip")andrecv.get("status")defloop_thread(self,conn:socket.socket,fd_port:int):"""服务器只判断client末尾的包头是否合法?:return:"""head_len=4self.user.append("192.168.1.105:88888")idx=1whileTrue:try:#继续接收数据包data=conn.recv(1024*4)iflen(data)>head_len:recv=json.loads(data[4:])recv=ast.literal_eval(recv)ifnotself.match_data(recv):#pop()抛出链表并返回抛出的数据,默认为lastAprint(f"clientfdaddr:{self.user.pop()}Connectedover!")break#为了模拟fd_port自增1,表示很多client连接到self.user.append(f"{recv.get('ip')}:{fd_port+idx}")print(f"当前服务器管理用户-->{self.user}")else:print(f"clientfdaddr:{self.user[-1]}Thedataisinvalid")exceptsocket.error:print(f"clientfdaddr:{self.user.pop()}已连接!”)breakelse:idx+=1conn.close()defstart(self):"""服务启动:return:"""whileTrue:conn,addr=self.sock.accept()t=Thread(target=self.loop_thread,args=(conn,addr[1]))t.start()if__name__=='__main__':server=HeartBeatServer(("127.0.0.1",14000),100)server.start()这里有一个重要的概念,这里为什么不能用self.sock,因为self.sock是服务器本身的句柄,而conn是服务器的句柄server接收client对象,所以这个conn是托管的,当client断开的时候,server通过conn挥手,如果是self.sock服务,就会关闭,在第5章的最后,我也写了一部分草案。