我们了解了socket,但是到目前为止,都是一个客户端(用户)在线、连接,而socketserver是对socket的再封装,并且他有一个主要的作用,实现了多用户的在线,实现了多并发
socketserver这个module简化了编写网络服务器
常用的两种类型:
class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)
TCPserver
class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)
UDPserver
这两种类的语法是相似的
还有两种不常用的:
class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)
class socketserver.UnixDatagramServer(server_address, RequestHandlerClass,bind_and_activate=True)
这四个类也有相应的继承关系,TCPServer继承一个基类叫做BaseServer,而UnixStreamServer和UDPServer都继承了TCPServer,UnixDatagramServer继承UPDServer,关系图如下:
那我们如何创建一个Socket服务器呢?让我们看一下官方的解释:
要想创建一个Socket服务器需要以下几步:
首先,你必须创建一个请
求处理类继承BaseRequestHandler
类并且覆盖(重写的意思)其中的handle()
方法,重写的这个方法会处理传入的请求
其次,你必须实例化一个服务器类(这里指的就是上面说到的四个类TCPServer、UDPServer等),传递这个服务器的地址和你第一步创建的请求处理类到你实例化的服务器(把这两个当作参数,实例化的时候传入),建议在使用服务器的时候带有声明
然后,你可以调用
handle_request()
或者server_forever()
方法来处理服务器中的一个或者多个请求
最后,调用
server_close()
来关闭socket链接(除非你声明)
handle_request()
只处理一个请求
server_forever()
处理多个请求
服务器端跟客户端所有的交互都在重写的
handle()
方法中
来创建一个简单的socketserver服务器吧:
# 创建服务器用到的模块
import socketserver
class MySelfServer(socketserver.BaseRequestHandler): # 第一步创建一个自己的server类,继承BaseRequestHandler类
# 重写BaseRequestHandler类中的handle方法,直接写在自己创建的类中就可以了
def handle(self): # 里面的内容为服务器端跟客户端的所有交互
while True:
# 接收数据
self.data = self.request.recv(1024).strip()
# 打印客户端ip地址和发送来的数据,这里可能会问为什么会有self.client_address这个参数,这个在父类构造函数中
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# 判断客户端是否断开
if not self.data:
print(self.client_address, '的链接断开了!') # 等待接收但接收为空则客户端断开
break
# 将接收到的数据大写发送回去
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# 第二步实例化四个类其中之一并传入服务器地址和上面自己创建的服务器类,这里自己实例化的TCPServer
server = socketserver.TCPServer((HOST, PORT), MySelfServer)
# 处理多个请求,这里注意的是虽然是处理多个请求,但是这句话并没有实现并发
server.serve_forever()
客户端就用之前学的一个比较简单的客户端:
import socket
flag = True
# 生成socket对象
client = socket.socket()
# 链接要链接的ip和port(端口)
client.connect(('localhost', 9999))
# while循环
while flag:
# 获得用户输入
msg = input("Enter your message('q' for quit):").strip()
# 判断是否为空
if len(msg) == 0:
print("Message can't be empty")
continue
# 发送数据
client.send(msg.encode())
# 判断是否为'q'
if msg != 'q':
# 接收数据
data = client.recv(1024)
# 打印接收到的数据
print(data)
else:
# 条件为False
flag = False
# 关闭socket链接
client.close()
print('Connection is broken')
这里要注意在win系统下客户端断开时可能会抛出异常,这个时候我们只要抓住这个异常就行了
这里呢我们并没有实现并发,可以试一试,开启第二个或者多个客户端的时候除了第一个客户端其他都会挂起等待,那我们如何实现多并发呢?
只需要修改服务器端一个地方也就是
# 第二步实例化四个类其中之一并传入服务器地址和上面自己创建的服务器类,这里自己实例化的TCPServer
server = socketserver.TCPServer((HOST, PORT), MySelfServer)
将TCPServer
改为ThreadingTCPServer
server = socketserver.ThreadingTCPServer((HOST, PORT), MySelfServer)
这样每有一个客户端连进来就会分配一个线程来处理请求
这样,实现了多个客户端的同时在线,并且互不干扰
他是如何实现的?想要理解其中过程可以通过解读源码,这里就不做深究,通过官方库的解释我们来简单理解一下:
Forking and threading versions of each type of server can be created using these mix-in classes, For instance, ThreadingUDPServer is created as follows 这句话翻译过来就是:
进程和线程版本可以通过这些混合类创建,线程UDPServer创建过程如下所示
具体的多线程实现的方法还是在类ThreadingMixIn中,这里不做深究
转载请注明出处
python自学技术互助扣扣群:670402334