本文要写的内容也称为Python套接字编程,并简单介绍socketserver类。参考教程主要是《Python核心编程》。
首先,客户端/服务器模型,客户端向服务器发送请求,在请求合理的情况下,服务器返回客户端需要的资源,这是此架构下的通信方式。
套接字:套接字是计算机网络的数据结构,体现了通信端点的概念。在开始任何类型的通信之前,网络应用必须创建套接字。可以将套接字比作电话插口,没有它将无法进行通信。AF_INET 网络套接字 是目前使用最广泛的套接字。
套接字地址:一个网络地址由主机-端口 对来组成;可以将套接字比作电话插口,那么主机名和 端口号就像是区号与电话号码的组合。
PS:有效端口号范围为0~65535,小于1024的端口号预留给了系统。
套接字分为面向连接的套接字和无连接的套接字
面向连接的通信提供序列化的,可靠的和不重复的数据交付,而没有边界记录,这基本上意味着每条消息可以拆分成很多片段,并且每一条消息片段都确保能够达到目的地,然后将它们按顺序组合在一起,最后加将完整消息传递给正在等待的应用程序。
实现这种连接类型的主要协议是传输控制协议 TCP。创建TCP套接字,必须使用SOCK_STREAM作为套接字类型。
实例:
创建TCP服务器伪代码如下:
sock = socket() #创建套接字
sock.bind() #将套接字与地址绑定
sock.listen() #监听连接
loop: #服务器无限循环
csock = sock.accept() #接受客户端连接
loop: #通信循环
cs.recv()/cs.send() #接收发送数据
cs.close() #关闭客户端套接字
ss.close() #关闭服务器套接字
服务器示例代码如下:
客户端代码示例如下:
无连接套接字是数据报类型的套接字,这意味着,在通信开始之前不需要建立连接。所以,在数据传输过程中并无法保证它的顺序性,可靠性或重复性,而且还可能丢失信息。但它的优势也是明显的,比如开销小,“成本低廉”。实现这种无连接类型的主要协议是用户数据报协议UDP。必须使用SOCK_DGRAM作为套接字类型
创建UDP服务器的伪代码如下:
sock.socket() #创建通信套接字
sock.bind() #将套接字与地址绑定
loop: #服务器无限循环
csock = sock.recvfrom()/sock.sendto() #接收发送数据
sock.close() #关闭服务器套接字
示例代码如下:
socketserver模块简单介绍
这个模块的不同之处在于,我们使用类来编写应用程序。因为以面向对象的方式处理事物有助于组织数据,以及逻辑性地将功能放在正确的地方。应用程序是事件驱动的,这意味着只有在系统中的事件发生时,它们才会工作。
socketserver模块有4个具体的类
class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True):使用TCP协议
class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True):使用UDP协议
class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True):只使用在UNIX平台上
class socketserver.UnixDatagramServer(server_address, RequestHandlerClass, bind_and_activate=True):只使用在UNIX平台上
这4个类的继承关系如下:
这四个类是同步处理请求的,每一个请求必须在前一个请求完成后再开始。所以如果每个请求都花费大量的时间的话,因为需要进行大量计算,那么它们是不合适的。解决方案就是创建一个分开的进程或者线程去处理每个请求,ForkingMixIn和ThreadingMixIn混入类可以用作支持异步行为。
创建一个服务器需要以下几步,首先,必须创建一个请求处理request handler类通过继承BaseRequestHandler类并且重写handler()方法。该方法将会处理进来的请求,第二步,必须继承server类中的一个,并且将它和request handler类一起传递到服务器地址。然后调用服务器的handle_request()或者serve_forever()方法去处理一个或多个请求。最后调用server_close()关掉套接字
socketserver.BaseServer类是此模块中服务器对象的超类,本身并不直接生成实例,而是通过派生关系,让子类生产实例,它的子类,比如TCPServer,UDPServer。
请求处理对象
socketserver.BaseQequestHandler是超类,每个子类都必须定义一个新的handle()方法,它的两个子类,StreamQequestHandler和DatagramQequestHandler.
示例代码也就是python docs上的代码:
需要注意的是,此片文章中,tcp的代码调试通过了,udp和socketserver的代码调试未通过,后续再努力