python学习笔记之--网络编程

2022-03-26  本文已影响0人  itsenlin

基本知识

这些基本的知识,网上有很多相关介绍,不是本章重点,有需要可以在网上查找相关资料。
这里学习一下python语言对底层网络编程的支持,这里只学习最常用的socket编程相关知识,详细说明可以参考官方文档:底层网络接口

socket模块

python有一个专门的socket模块来支持底层网络通信。是对Unix系统调用和套接字库接口的直译。

socket编程基本套路

  1. TCP服务端
    s = socket()  # 创建一个服务端socket
    s.bind()      # 绑定socket地址(ip+port)
    s.listen()    # 监听此地址是否有连接
    loop:
        cs = s.accept() # 阻塞等待客户端连接,连接成功返回新的套接字对象,用于在此连接上收发数据
        comm_loop:
            cs.recv()/cs.send() # 通信:接收数据/发送数据
        cs.close() # 关闭通信套接字对象
    s.close() # 关闭服务端套接字对象
    
  2. TCP客户端
    cs = socket()  # 创建一个客户端socket
    cs.connect()      # 通过服务端地址(ip + port)尝试连接服务端
    comm_loop:
        cs.send()/cs.recv() # 通信:发送数据/接收数据
    cs.close() # 关闭客户端套接字对象
    
  3. UDP服务端
    ss = socket()  # 创建一个服务端socket
    ss.bind()      # 绑定服务端地址
    comm_loop:
        cs.recvfrom()/cs.sendto() # 通信:接收数据/发送数据
    cs.close() # 关闭客户端套接字对象
    

说明: UDP无连接,不需要监听。先被动接收数据,会返回客户端的地址,后面就可以根据客户端地址主动发送消息。

  1. UDP客户端
    cs = socket()  # 创建一个客户端socket
    comm_loop:
        cs.sendto()/cs.recvfrom() # 通信:发送数据/接收数据
    cs.close() # 关闭客户端套接字对象
    

socket通信实例

先从一个TCP实例开始学习,功能比较简单:

  1. 一个客户端,一个服务器端,两个python程序可以放在两台电脑上运行
  2. 客户端给服务端发送一个消息;服务器端接收到消息之后,加上一个时间戳再返回给客户端
  3. 无消息则结束

说明:socket类实现了__enter____exit__,可以使用with语句自动实现close操作,也即使用with语句可以不用主动调用socket.close()接口

模块说明

常量名 说明
socket.AF_INET 一种用于ipv6的地址族,一个四元组(host, port, flowinfo, scope_id)表示地址
socket.AF_INET6 一种socket地址族(用于ipv4,也是目前常用的)使用一个(ip, port)元组表示地址
socket.SOCK_STREAM 面向连接(TCP)的socket类型
socket.SOCK_DGRAM 面向无连接(UDP)的socket类型

常用接口信息如下表

接口名 连接方式 说明
socket.bind(address) TCP/UDP 服务端socket绑定到地址address
socket.listen([backlog]) TCP 启动一个服务器用于接受连接。backlog表示系统允许暂未 accept 的连接数,超过后将拒绝新连接。最低为 0(小于 0 会被置为 0),未指定则自动设为合理的默认值。
socket.accept() TCP 接受一个连接。此 socket 必须绑定到一个地址上并且监听连接。返回一个 (conn, address) 对:其中 conn 是一个新的套接字对象,用于在此连接上收发数据,address 是连接另一端的套接字所绑定的地址。
socket.connect(address) TCP/UDP 连接到 address 处的远程套接字。
socket.recv(bufsize[, flags]) TCP 从套接字接收数据。返回值是一个字节对象,表示接收到的数据。bufsize 指定一次接收的最大数据量。可选参数 flags 的含义请参阅 Unix 手册页 recv(2),它默认为零。
socket.send(bytes[, flags]) TCP 发送数据给套接字。本套接字必须已连接到远程套接字。可选参数 flags 的含义与上述 recv() 中的相同。
socket.recvfrom(bufsize[, flags]) UDP 从套接字接收数据。返回值是一对 (bytes, address),其中 bytes 是字节对象,表示接收到的数据,address 是发送端套接字的地址。可选参数 flags 的含义请参阅 Unix 手册页 recv(2),它默认为零。
socket.sendto(bytes, address) UDP 发送数据给套接字。由 address 指定目标套接字。可选参数 flags 的含义与上述 recv() 中的相同。
异常名 说明
socket.error 一个被弃用的 OSError 的别名。
socket.herror OSError的子类,本异常通常表示与地址相关的错误。
socket.gaierror OSError的子类,来自 getaddrinfo()getnameinfo(),表示与地址相关的错误。附带的值是一对 (error, string),代表库调用返回的错误。
socket.timeout OSError的子类,当套接字发生超时,且事先已调用过 settimeout()(或隐式地通过 setdefaulttimeout())启用了超时,则会抛出此异常。

SocketServer模块

socketserver模块是一个用于网络服务器编写的框架,简化了编写网络服务器的任务。例如上面TCP服务器端代码可以使用此模块改写如下:

import socketserver

class MyTCPHandler(socketserver.StreamRequestHandler):

    def handle(self):
        # self.rfile is a file-like object created by the handler;
        # we can now use e.g. readline() instead of raw recv() calls
        self.data = self.rfile.readline().strip()
        print("{} wrote:".format(self.client_address[0]))
        print(self.data)
        # Likewise, self.wfile is a file-like object used to write back
        # to the client
        self.wfile.write(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "localhost", 21567

    # Create the server, binding to localhost on port 9999
    with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
        # Activate the server; this will keep running until you
        # interrupt the program with Ctrl-C
        server.serve_forever()

模块说明

常用实体服务器类:

请求处理句柄对象:

当然此框架还提供了更加强大的功能,具体可以参考官方文档

上一篇 下一篇

猜你喜欢

热点阅读