网络编程之并发网络编程

之前使用socket模块实现的网络编程都不能并发进行连接和通信的, 即一个客户端需要等待服务器和另一个客户端通信完成后才能和服务端进行连接和通信。

python3中提供有一个高级内置模块socketserver来帮助我们进行并发的网络编程。

socketserver模块介绍

SocketServer模块处理网络请求的功能,可以通过两个主要的类来实现:一个是服务器类,一个是请求处理类。
服务器类 处理通信问题,如监听一个套接字并接收连接等;

请求处理类 处理“协议”问题,如解释到来的数据、处理数据并把数据发回给客户端等。

这种实现将服务器的实现过程和请求处理的实现过程解耦,这意味着我们可以将不同的服务器实现和请求处理实现结合起来来处理一些定制的协议,例如一个TCP服务器类和一个流请求处理类结合,处理基于TCP的网络请求。同时,也可以基于SocketServer模块中的服务器类和请求处理类,实现网络层之上应用层的服务器和请求处理实现,例如基于TCP服务器类实现HTTP服务器,基于流处理请求类实现HTTP请求处理类等。

SocketServer模块中定义了五种服务器类

  • BaseServer(服务器的基类,定义了API)
  • TCPServer(使用TCP/IP套接字)
  • UDPServer(使用数据报套接字)
  • UnixStreamServer(使用UNIX域套接字,只适用UNIX平台)
  • UnixDatagramServer(使用UNIX域套接字,只适用UNIX平台)

SocketServer模块中定义了两种Mixin类, 用于支持异步(Fork用于创建多进程, Thread用户创建多线程)

  • ForkingMixIn
  • ThreadingMixIn

SocketServer模块服务器类与Mixin类组合得到

  • class ForkingUDPServer(ForkingMixIn,UDPServer):pass
  • class ForkingTCPServer(ForkingMixIn,TCPServer):pass
  • class ThreadingUDPServer(ThreadingMixIn,UDPServer):pass
  • class ThreadingTCPServer(ThreadingMixIn,TCPServer):pass

创建TCP服务端

import socketserver


ADDR = ('127.0.0.1', 8080)  
  
class MyRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        print(self.request)   # 套接字对象
        print(self.client_address)  # 客户端的地址信息

        self.request.close()
    
  
  
tcpServer = socketserver.TCPServer(ADDR, MyRequestHandler)  
  
tcpServer.serve_forever() 

我们从socketserver的BaseRequestHandler类中派生出一个子类,并重写handle()函数。在BaseRequest 类中,这个函数什么也不做。在有客户消息进来的时候,handle()函数就会被调用。

创建UDP服务端

import socketserver


ADDR = ('127.0.0.1', 8080)  
  
class MyRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        print(self.request[0])  # 客户端发送的消息
        print(self.request[1])  # 套接字镀锡
        print(self.client_address)

        self.request.close()
    
  
  
tcpServer = socketserver.UDPServer(ADDR, MyRequestHandler)  
  
tcpServer.serve_forever()

如果要处理多连接问题,那么有三种主要的方法能实现这个目的:分叉(forking)、线程(threading)以及异步I/O(asynchronous I/O)。通过对socketserver服务器使用混入类(mix-in class),派生进程和线程很容易处理。即使要自己实现它们,这些方法也很容易使用。它们确实有缺点:分叉占据资源,并且如果有太多的客户端时分叉不能很好分叉(尽管如此,对于合理数量的客户端,分叉在现代的UNIX或者Linux系统中是很高效的,如果有一个多CPU系统,那系统效率会更高);线程处理能导致同步问题。使用socketserver框架创建分叉或者线程服务器非常简单

创建TCP分叉服务端

import socketserver


ADDR = ('127.0.0.1', 8889)


class Server(socketserver.ForkingMixIn, socketserver.TCPServer):
    pass


class MyRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        print(self.request)
        print(self.client_address)


tcpServer = Server(ADDR, MyRequestHandler)
tcpServer.serve_forever()

创建udp分叉服务端同理即可

创建TCP多进程服务端

import socketserver


ADDR = ('127.0.0.1', 8889)


class Server(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass


class MyRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        print(self.request)
        print(self.client_address)


tcpServer = Server(ADDR, MyRequestHandler)
tcpServer.serve_forever()

创建udp多进程服务端同理即可

注意:

ThreadingUDPServer与ThreadingTCPServer类中的特有属性:

  • daemon_threads=False #默认值是False表示创建的线程都不是daemon线程,改为True表示创建的所有线程都是daemon线程
  • block_on_close=False #默认值为Fasle,如果为True,可以设置为守护线程

猜你喜欢

转载自www.cnblogs.com/featherwit/p/13367702.html