美文网首页
Python 网络编程之二(socketserver 模块)

Python 网络编程之二(socketserver 模块)

作者: Manchangdx | 来源:发表于2019-05-10 16:53 被阅读0次

    一、socketserver 模块简介

    socketserver 是 Python 标准库中的一个高级模块,它的目标是简化很多样板代码,这些代码是创建网络客户端和服务器所必需的代码。这个模块中有创建好的各种各样的类,如下表所示。

    模块中的类 描述
    BaseServer 包含核心服务器功能和 mix-in 类的钩子,仅用于推导,这样不会创建这个类的实例,可以用 TCPServer 或 UDPServer 创建类的实例
    TCPServer / UDPServer 基础网络的同步服务器
    UnixStreamServer / UnixDatagramServer 基于文件的同步服务器
    ForKingMixIn / ThreadingMinIn 核心派出或线程功能;只用作 mix-in 类与一个服务器类配合实现一些异步性;不能直接实例化
    ForKingTCPServer / ForkingUDPServer ForKingMixIn 和 TCPServer / UDPServer 的组合
    ThreadingTCPServer / ThreadingUDPServer ThreadingMixIn 和 TCPServer / UDPServer 的组合
    BaseRequestHandler 包含处理服务请求的核心功能,仅用于推导,无法创建实例,可以使用 StreamRequestHandler 或 DatagramRequestHandler 创建类的实例
    StreamRequestHandler / DatagramRequestHandler 实现 TCP / UDP 服务器的处理器

    通过 Python 网络编程一(CS 架构和 socket 模块)展示的基本 TCP 示例,我们将使用 socketserver 创建一个 TCP 服务器。你会发现它们之间存在明显的相似性,但是也应该看到我们如何处理一些繁琐的工作,于是你不必担心样板代码。这些代表了你能够编写的最简单的同步服务器。除了为你隐藏了实现细节之外,另一个不同之处是,我们现在使用类来编写应用程序。因为以面向对象的方式处理事务有助于组织数据,将功能放在逻辑正确的地方。你还会注意到,应用程序现在是事件驱动的,这意味着只有在系统中的事件发生时,它们才会工作。

    事件包括消息的发送和接收。事实上,你会看到类定义只包括一个用来接收客户端消息的事件处理程序。所有其他的功能都来自使用的 socketserver 类。此外,GUI 编程也是事件驱动的。你会立即注意到它们的相似性,因为最后一行代码通常是一个服务器的无限循环,它等待并响应客户端的服务请求。它工作起来几乎与本章前面的基础 TCP 服务器中的无限 while 循环一样。
    在原始服务器循环中,我们阻塞等待请求,当接收到请求时就对其提供服务,然后继续等待。在此处的服务器循环中,并非在服务器中创建代码,而是定义一个处理程序,这样当服务器接收到一个传入的请求时,服务器就可以调用你的函数。

    二、使用 socketserver 创建 TCP 服务器

    使用 TCPServer 创建 TCP 服务,将以下代码写入 tcp_ss.py 文件中:

    from socketserver import TCPServer, StreamRequestHandler
    import time
    
    ADDR = ('', 1234)
    BUFSIZ = 1024
    
    
    # 创建 StreamRequestHandler 类的子类
    class MyRequestHandler(StreamRequestHandler):
        # 重写 handle 方法,该方法在父类中什么都不做
        # 当客户端主动连接服务器成功后,自动运行此方法
        def handle(self):
            # client_address 属性的值为客户端的主机端口元组
            print('... connected from {}'.format(self.client_address))
            # request.recv 方法接收客户端发来的消息
            data = self.request.recv(BUFSIZ)
            # request.sendall 方法发送消息给客户端
            self.request.sendall('[{}] {}'.format(
                time.ctime(), data.decode()).encode())
    
    
    def main():
        # 创建 TCP 服务器并启动,该服务器为单线程设计,不可同时为两个客户端收发消息
        # 该服务器每次连接客户端成功后,运行一次 handle 方法然后断开连接
        # 也就是说,每次客户端的请求就是一次收发消息
        # 连续请求需要客户端套接字不断重新创建
        tcp_server = TCPServer(ADDR, MyRequestHandler)
        print('等待客户端连接...')
        try:
            tcp_server.serve_forever()  # 服务器永远等待客户端的连接
        except KeyboardInterrupt:
            tcp_server.server_close()   # 关闭服务器套接字
            print('\nClose')
            exit()
    
    
    if __name__ == '__main__':
        main()
    

    创建 TCP 客户端,仍然使用 socket 模块,将以下代码写入 tcp_sc.py 文件:

      1 from socket import socket, AF_INET, SOCK_STREAM
      2
      3 ADDR = ('localhost', 1234)
      4 BUFSIZ = 1024
      5
      6 # 这个循环不断运行下去
      7 # 每次连接服务器,发送并接收消息,就是一次循环
      8 # 循环结束时关闭客户端套接字,下次循环重新创建
      9 while True:
     10     tcp_client_sock = socket(AF_INET, SOCK_STREAM)
     11     tcp_client_sock.connect(ADDR)
     12     data = input('输入内容:')
     13     if not data:
     14         break
     15     tcp_client_sock.send(data.encode())
     16     data = tcp_client_sock.recv(BUFSIZ)
     17     if not data:
     18         break
     19     print(data.decode())
     20     tcp_client_sock.close()
    

    相关文章

      网友评论

          本文标题:Python 网络编程之二(socketserver 模块)

          本文链接:https://www.haomeiwen.com/subject/mooaoqtx.html