Python32 Socket Serv
- 2020 年 1 月 6 日
- 筆記
类型
- socketserver有几种类型: class socketserver.TCPServer:用于TCP class socketserver.UDPServer:用于UDP class socketserver.UnixStreamServer:用于Unix的TCP class socketserver.UnixDatagramServer:用于Unix的UDP

TCPServer继承了BaseServer UnixStreamServer继承了TCPServer
- 创建socket server至少分以下几步: 1、必须创建一个请求处理类,并且这个类要继承BaseRequestHandler,还要重写父类里的handle方法(跟客户端所有的交互都是在handle中写的)。 2、必须要实例化一个协议server(如TCPServer),并且传递server ip和你上面创建的请求处理类,给这个TCPServer(实例化的时候将IP和请求处理类传给TCPServer)。 3、然后可以根据上面的实例来处理请求: server.handle_request() #只处理一个请求 server.handle_forever() #处理多个请求,永远执行(一般都是用这个) 4、调用server_close()去关闭
server端: import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): '''第1步:创建处理类,继承Base。 客户端每一次请求过来都会实例化这个类''' def handle(self): '''第1步:重写handle方法,handle默认存在父类中代码是空的。 客户端所有交互都在handle中完成''' while True: #使其可以循环发送数据 self.data = self.request.recv(1024).decode().strip() #这里的self.request.recv相当于之前用的conn.recv print ("{} wrote:".format(self.client_address[0])) #打印客户端的IP地址信息 print (self.data) #打印数据信息 self.request.send(self.data.upper().encode('utf-8')) #传回数据给客户端,只是upper了一下 #sendall就是重复调用send if __name__ == "__main__": HOST,PORT = "localhost",9999 server = socketserver.TCPServer((HOST,PORT),MyTCPHandler) #第2步:实例化TCPServer,并将IP和MyTCPHandler当做参数传给请求处理类 #监听客户端的每一个请求,就会实例化MyTCPHandler这个类,拿MyTCPHandler的handle与客户端交互。 server.serve_forever() #第3步:允许永远处理多个请求 client端: import socket client = socket.socket() client.connect(('localhost',9999)) while True: msg = input(">>:").strip() if len(msg) == 0:continue client.send(msg.encode('utf-8')) data = client.recv(1024) print ("recv:",data.decode()) client.close() client执行结果: >>:abc recv: ABC >>:efg recv: EFG >>:hhh recv: HHH >>: server执行结果: 127.0.0.1 wrote: abc 127.0.0.1 wrote: efg 127.0.0.1 wrote: hhh client断开后server报错: ---------------------------------------- Exception happened during processing of request from ('127.0.0.1', 53933) Traceback (most recent call last): File "D:python37libsocketserver.py", line 313, in _handle_request_noblock self.process_request(request, client_address) File "D:python37libsocketserver.py", line 344, in process_request self.finish_request(request, client_address) File "D:python37libsocketserver.py", line 357, in finish_request self.RequestHandlerClass(request, client_address, self) File "D:python37libsocketserver.py", line 712, in __init__ self.handle() File "E:/python/代码练习/A2.py", line 11, in handle self.data = self.request.recv(1024).decode().strip() ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。 ---------------------------------------- #可以看到这里报错ConnectionResetError: [WinError 10054]
修改server端: import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): def handle(self): while True: #使其可以循环发送数据 try: #使用try的话就不需要使用 if not data的方式来判断客户端断开时,无数据的情况了 self.data = self.request.recv(1024).decode().strip() #这里的self.request.recv相当于之前用的conn.recv print ("{} wrote:".format(self.client_address[0])) print (self.data) self.request.send(self.data.upper().encode('utf-8')) except ConnectionResetError as e: print ("err:",e) break #这里一定要break,不然就会一直死循环 if __name__ == "__main__": HOST,PORT = "localhost",9999 server = socketserver.TCPServer((HOST,PORT),MyTCPHandler) server.serve_forever() server执行结果: 127.0.0.1 wrote: abc 127.0.0.1 wrote: 123 err: [WinError 10054] 远程主机强迫关闭了一个现有的连接。 #客户端断开连接后,就通过断言的方式抓到错误了。
上面的代码目前还不能支持多并发,如果有多个并发,后面的并发就会被挂起; 如果要并发的话,需要修改一下代码。

通过ctrl点TCPServer

可以看到TCPServer是继承了BaseServer

修改server端: import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): def handle(self): while True: #使其可以循环发送数据 try: #使用try的话就不需要使用 if not data的方式来判断客户端断开时,无数据的情况了 self.data = self.request.recv(1024).decode().strip() print ("{} wrote:".format(self.client_address[0])) print (self.data) self.request.send(self.data.upper().encode('utf-8')) except ConnectionResetError as e: print ("err:",e) break if __name__ == "__main__": HOST,PORT = "localhost",9999 server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler) # 上面的代码需要使用ThreadingTCPServer server.serve_forever() client 1执行结果: >>:test 1 recv: TEST 1 >>: client 2执行结果: >>:test 2 recv: TEST 2 >>: client 3执行结果: >>:test 3 recv: TEST 3 >>: server 执行结果: 127.0.0.1 wrote: test 1 127.0.0.1 wrote: test 2 127.0.0.1 wrote: test 3

可以看到server端现在支持多并发,没有被挂起;每来一个请求会开启一个新线程与server交互;每个线程都是独立的,10个线程,就可以做10件事情。
通过ctrl点ThreadingTCPServer

可以看到将TCPServer这个类传了进去 同时还传了ThreadingMixIn;TCPServer是负责与客户端交互,而多线程都是由ThreadingMixIn实现的。
ctrl点ThreadingMixIn

这部分就是多线程的主要代码