1.socketserver介绍
-
socketserver
是标准库中的一个高级模块; -
socketserver
模块是python提供的内置的用于快捷开发服务端程序的一个服务器框架,通过封装大量实现的方式减少开发人员工作量的同时能快捷开发出具有较高质量的服务端程序;
+------------+
| BaseServer |
+------------+
|
v
+-----------+ +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+
|
v
+-----------+ +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+
- socketserver模块主要包含的非Unix服务器类
TCPserver
、UCPserver
、ThreadingTCPServer(ThreadingMixIn, TCPServer)
、ThreadingUDPServer(ThreadingMixIn, UDPServer)
、ForkingTCPServer(ForkingMixIn, TCPServer)
、ForkingUDPServer(ForkingMixIn, UDPServer)
;
2.Socketserver模块四个基本的服务器类
-
TCPServer
,基本的网络同步TCP服务器; -
UDPServer
,基本的网络同步UDP服务器; -
UnixStreamServer
,使用UNIX域套接字实现面向数据流协议的服务器,继承自TCPServer; -
UnixDatagramServer
,使用UNIX域套接字实现数据报协议的服务器,继承自UDPServer; -
这四个类型同步地处理请求,也就是说一个请求没有完成之前是不会处理下一个请求的;
3.Socketserver模块的两个异步处理类
ForkingMixIn
,将UNIX进程分支添加到服务器的混合方法,使用该方法可以让服务器服务多个客户;
ThreadingMixIn
,修改服务器的混合类,可以使用多线程服务多个客户端;
继承自这两个类型的服务端在处理新的客户端连接时不会阻塞,而是创建新的进/线程专门处理客户端的请求;
4.BaseRequestHandle类的实例化可以实现的方法
-
setup()
:该方法在handle()之前调用,默认什么都不做,如果希望服务器实现更多连接设置,则无需调用该方法; -
handle()
:调用该方法执行实际的请求操作,调用函数可以不带任何参数,默认什么都不做; -
finish()
: 环境清理,在handle()之后执行清除操作,默认什么都不做,如果setup()和handle()方法都不生成异常,则无需调用该方法;
5.TCPServer服务器端代码实现
import socketserver
import threading
from pprint import pprint
class Handler(socketserver.BaseRequestHandler):
def handle(self):
print('当前的server类型: {}'.format(self.server))
print('当前的socket连接对象: {}'.format(self.request))
print('当前的客户端地址: {}'.format(self.client_address))
print('线程列表: {}'.format(threading.enumerate()))
print('当前的线程:{}'.format(threading.current_thread()))
server = socketserver.TCPServer(('127.0.0.1', 9000), Handler)
server.serve_forever()
当前的server类型: <socketserver.TCPServer object at 0x107dcfac8>
当前的socket连接对象: <socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61609)>
当前的客户端地址: ('127.0.0.1', 61609)
线程列表: [<_MainThread(MainThread, started 4486772160)>]
当前的线程:<_MainThread(MainThread, started 4486772160)>
6.socketserver模块创建服务器步骤
-
创建一个请求处理类继承于BaseRequestHandler类, 且覆盖父类的handler方法,重写的这个方法会处理传入的请求;
-
实例化一个服务器类,传递这个服务器的地址和你第一步创建的请求处理类到你实例化的服务器;
-
调用server实例的serve_forever()方法(可以处理多个请求)或者handle_request()方法(只处理一个请求)来处理服务器中的一个或者多个请求; 最后调用server_close()来关闭socket链接;
7.多客户端的socketserver实现
############################## 服务器端 ##############################
import socketserver
import threading
class Handler(socketserver.BaseRequestHandler):
clients = {}
def setup(self):
super().setup()
self.event = threading.Event()
self.clients[self.client_address] = self.request
def handle(self):
super().setup()
while not self.event.is_set():
data = self.request.recv(1024).decode()
if data == 'quit':
break
msg = "{} 说 {}".format(self.client_address, data).encode()
print(self.clients)
if self.client_address in self.clients.keys():
self.clients[self.client_address].send(msg)
# if request self.clients.values():
# request.send(msg)
print('server end')
def finish(self):
super().finish()
self.clients.pop(self.client_address)
self.event.set()
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('127.0.0.1', 9000), Handler)
threading.Thread(target=server.serve_forever, daemon=True).start()
while True:
cmd = input('请输入您想说的话: ').strip()
if cmd == 'quit':
print(cmd)
server.shutdown()
server.server_close()
break
else:
print('您可以输入quit来停止服务器! ')
############################## 客户端 ##############################
import socket
# 创建TCP连接
socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_instance.connect(('127.0.0.1', 9000))
while True:
cmd = input("请输入您想说的话:")
socket_instance.send(cmd.encode())
data = socket_instance.recv(1024).decode()
print(data)
网友评论