zoukankan      html  css  js  c++  java
  • 03Python网络编程系列之服务端

    # 这里边是一个定义了服务端的一系列函数,是Python网络编程这本书第七章的第一个例子。
    # 这是供后边函数进行调用了,然后我们来进行研究网络的单线程编程,多线程编程、异步网络编程等。

    # 导入网络编程socket、时间time、cmd参数获取模块
    import argparse, socket, time

    # 定义一个字典用来存放发送给客户端的消息。
    aphorisms = {b'Beautiful is better than?': b'Ugly.',
    b'Explicit is better than?': b'Implicit.',
    b'Simple is better than?': b'Complex.'}

    # 获取答案, 如果客户端发送了问题,就从上边的字典里边获取,如果没有的话就返回我不知道的错误。
    def get_answer(aphorism):
    """Return the string response to a particular Zen-of-Python aphorism."""
    time.sleep(0.0) # increase to simulate an expensive operation
    return aphorisms.get(aphorism, b'Error: unknown aphorism.')

    # 定义一个函数用来获取终端需要传入的参数。 host:主机IP或者名称 -p:端口,默认为1060
    # 返回值是一个元祖,包含IP端口。
    def parse_command_line(description):
    """Parse command line and return a socket address."""
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('host', help='IP or hostname')
    parser.add_argument('-p', metavar='port', type=int, default=1060,
    help='TCP port (default 1060)')
    args = parser.parse_args()
    address = (args.host, args.p)
    return address

    # 创造一个socket套接字,这里的入参是上边那个函数的出参。
    def create_srv_socket(address):
    """Build and return a listening server socket."""
    # 创造一个套接字。
    listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置。
    listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 服务端绑定IP和端口。
    listener.bind(address)
    # 设置服务端能够监听的数量,这里设置的是最大能够同时监听64个。
    listener.listen(64)
    # 打印出绑定的IP端口,服务端绑定的。
    print('Listening at {}'.format(address))
    # 返回这个套接字。
    return listener

    # 一直持续不断的进行监听, 观察有没有客户端和服务端进行连接。
    # 这里的入参是上边函数的出参
    def accept_connections_forever(listener):
    """Forever answer incoming connections on a listening socket."""
    # 死循环
    while True:
    # 服务端一直在监听端口,看有没有客户端进行连接。
    # 这个是阻塞的,如果有的话那么才会进行下边的操作。
    sock, address = listener.accept()
    # 打印出客户端IP端口
    print('Accepted connection from {}'.format(address))
    handle_conversation(sock, address)

    # 处理连接对话函数。
    def handle_conversation(sock, address):
    """Converse with a client over `sock` until they are done talking."""
    try:
    while True:
    # 这里一直处理客户端的请求。
    handle_request(sock)
    # 接收异常,代表着客户端断开了连接。
    except EOFError:
    print('Client socket to {} has closed'.format(address))
    # 如果有其他错误,我们也需要进行接收下来。
    except Exception as e:
    print('Client {} error: {}'.format(address, e))
    # 最后关闭服务端的套接字。
    finally:
    sock.close()

    # 处理请求函数。
    def handle_request(sock):
    """Receive a single client request on `sock` and send the answer."""
    # 这里我们调用函数进行接收客户端发送过来的消息。
    aphorism = recv_until(sock, b'?')
    # 然后调用获取答案函数,将我们的答案回复给客户端。
    answer = get_answer(aphorism)
    # 服务端进行发送消息
    sock.sendall(answer)

    # 服务端和客户端进行连接后,一直进行接收客户端发送过来的消息,直到客户端发送了suffix
    # 这里我们的入参为?,如果客户端发送了suffix就代表着客户端发送完了消息。就需要进行关闭了。
    def recv_until(sock, suffix):
    """Receive bytes over socket `sock` until we receive the `suffix`."""
    # 接收数据,
    message = sock.recv(4096)
    # 如果数据为空。就抛出一个连接关闭的错误。
    if not message:
    raise EOFError('socket closed')
    # 判断接收的消息最后是否是suffix,如果是地话,那我们就直接反悔了。
    # 如果不是,就代表着客户端还有数据进行发送,服务端就需要继续进行接收。
    while not message.endswith(suffix):
    # 能够进来while循环,就代表着客户端还有数据进行发送,
    # 那么我们需要继续进行接收
    data = sock.recv(4096)
    # 如果客户端的数据为空。
    # 再次抛出一个异常。
    if not data:
    raise IOError('received {!r} then socket closed'.format(message))
    message += data
    # 返回接收的数据。
    return message
  • 相关阅读:
    mysql 5.5多实例部署【图解】
    mysql多实例的配置和管理
    Xtrabackup数据全备份与快速搭建从服务器
    REST API设计指导——译自Microsoft REST API Guidelines(四)
    REST API设计指导——译自Microsoft REST API Guidelines(三)
    REST API设计指导——译自Microsoft REST API Guidelines(二)
    REST API设计指导——译自Microsoft REST API Guidelines(一)
    【活动提示】免费帮你做系统,请点击!
    程序员最大的悲哀是什么?
    工欲善其事必先利其器——产品篇
  • 原文地址:https://www.cnblogs.com/cong12586/p/14071785.html
Copyright © 2011-2022 走看看