一、概述
我们之前的用户都是不支持多并发的,所以我们现在需要一个支持多用户,实现一个并发处理,我们接下来就不能不接触socketserver这个模块。前面讲的socket都是铺垫,后面需要真正使用的是socketserver(The socketserver
module simplifies the task of writing network servers)
二、socketserver类型
2.1、TCPServer
说明:这个是用于TCP协议的,它在客户端和服务器之间提供连续的数据流
英文解释:This uses the Internet TCP protocol, which provides for continuous streams of data between the client and server.
class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)
2.2、UDPServer
说明:用于UDP协议的,并非连续的数据包,中间传输可能会丢失。传入的参数和TCPServer是一样的
英文解释:This uses datagrams, which are discrete packets of information that may arrive out of order or be lost while in transit. The parameters are the same as for TCPServer
.
class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)
2.3、UnixStreamServer和UnixDatagramServer
说明:这个很少用在TCP和UDP类中,但是用正在Unix领域里的sockets;传入的参数和TCPServer是一样的。
英文解释:These more infrequently used classes are similar to the TCP and UDP classes, but use Unix domain sockets; they’re not available on non-Unix platforms. The parameters are the same as for TCPServer
.
class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)
class socketserver.UnixDatagramServer(server_address, RequestHandlerClass,bind_and_activate=True)
2.4、五个类实例化过程
There are five classes in an inheritance diagram, four of which represent synchronous servers of four types:
+------------+ | BaseServer | +------------+ | v +-----------+ +------------------+ | TCPServer |------->| UnixStreamServer | +-----------+ +------------------+ | v +-----------+ +--------------------+ | UDPServer |------->| UnixDatagramServer | +-----------+ +--------------------+
三、创建socketserver步骤
3.1、中文解释
- 必须自己创建一个请求处理类,并且这个类要继承BaseRequestHandlerclass,并且还有重写父类里的handle()
- 你必须实例化TCPServer,并且传递server ip和你在第一步创建的请求处理类给这个TCPServer
- 接下来调server.handle_request()(只处理一个请求)或者server.serve_forever()(处理多个客户端请求,永远执行)
- 调用server_close()去关闭socket
3.2、英文解释
- First, you must create a request handler class by subclassing the
BaseRequestHandler
class and overriding itshandle()
method; this method will process incoming requests. - Second, you must instantiate one of the server classes, passing it the server’s address and the request handler class.
- Then call the
handle_request()
orserve_forever()
method of the server object to process one or many requests. - Finally, call
server_close()
to close the socket.
四、简单的代码实现
4.1、服务端代码实现
代码逻辑:先定义一个handler类->实例化TCPServer->serve_forever()实现处理多个客户端请求
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler): #继承BaseRequestHandler这个基类
"""
The request handler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
while True:
try:
self.data = self.request.recv(1024)
print("{0} write:".format(self.client_address[0]))
print(self.data)
self.request.send(self.data.upper())
except ConnectionResetError as e: #抓去异常,这个异常当客户端断开服务端出现断开,这个只有在python3.0才会有
print("error:",e)
break
if __name__ == "__main__":
HOST,PORT = "localhost",9999
server = socketserver.TCPServer((HOST,PORT),MyTCPHandler) #每起一个TCPServer都会实例化MyTCPHandler这个类
server.serve_forever() #实现多个链接
server.server_close() #关闭socketserver
注意了:客户端所有的交互都是在handler里面完成的,每一个请求过来之后,它的请求就会被分配,它的请求的处理规则就是咋子handle里面规定的。服务器收到客户端的数据为空,表明客户端已经断开。
4.2、客户端的代码
import socket
client = socket.socket()
client.connect(("localhost",9999))
while True:
cmd = input(">>>:").strip()
if len(cmd) == 0:continue
client.send(cmd.encode("utf-8"))
cmd_res = client.recv(500)
print(cmd_res.decode("utf-8",'ignore'))
client.close()