zoukankan      html  css  js  c++  java
  • Python网络编程——编写一个简单的回显客户端/服务器应用

    今天将python中socket模块的基本API学习完后,照着书上的实例编写一个套接字服务器和客户端。采用python3.5版本,在注释中会标明python2和python3的不同之处。

    1.代码

    (1)服务器端及对应代码解释

     1 # ! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # 编写回显服务器
     4 
     5 import socket
     6 import sys
     7 import argparse
     8 
     9 # 定义常量
    10 host = 'localhost'
    11 data_payload = 2048
    12 backlog = 5
    13 
    14 
    15 def echo_server(port):
    16 
    17     # 创建一个TCP socket
    18     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    19 
    20     # 设置TCP套接字关联选项——重用地址
    21     sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    22 
    23     # 建立套接字端口
    24     server_address = (host, port)
    25     print("Starting up echo server on %s port %s" % server_address)
    26 
    27     # 将socket绑定到server_address地址
    28     sock.bind(server_address)
    29 
    30     # 监听客户端
    31     # backlog指定最多允许多少个客户连接到服务器。它的值至少为1。收到连接请求后,这些请求需要排队,如果队列满,就拒绝请求。
    32     # 这里设定为5
    33     sock.listen(backlog)
    34     # 在调用 Listen 之前,必须首先调用 Bind 方法,否则 Listen 将引发 SocketException。
    35     while True:
    36         print("Waiting to receive message from client")
    37 
    38         # 调用accept方法时,socket会时入“waiting”状态。客户请求连接时,方法建立连接并返回服务器。
    39         # accept方法返回一个含有两个元素的 元组(connection,address)。第一个元素connection
    40         # 是新的socket对象,服务器必须通过它与客户通信;第二个元素 address是客户的Internet地址。
    41         client, address = sock.accept()
    42 
    43         # 指定data最大长度为2048字节
    44         data = client.recv(data_payload)
    45         if data:
    46             print("Data: %s" % data)
    47             client.send(data)
    48             print("sent %s bytes back to %s" % (data, address))
    49         # 关闭连接
    50         client.close()
    51 
    52 if __name__ == '__main__':
    53     # 创建一个解析对象,其中描述为"Socket Error Examples"
    54     parser = argparse.ArgumentParser(description='Socket Server Example')
    55     # 采用add_argument方法
    56     # name or flags —— 必须的参数,该参数接收选项参数或者是位置参数
    57     # action:
    58         # (1)store —— 默认action模式,储存值到指定变量
    59         # (2)store_const —— 储存值在参数的const部分指定,多用于实现非布尔的命令行flag
    60         # (3)store_true/store_false —— 布尔开关。可以2个参数对应一个变量
    61         # (4)append —— 储存值到列表,储存值在参数的const部分指定
    62         # (5)append_const —— 储存值到列表,储存值在参数的const部分指定
    63         # (6)version —— 输出版本信息然后退出
    64     # type —— 把从命名行输入的结果转成设置的类型,通常用来检查值的范围,以及合法性。默认string  
    65     # required —— 指定某个选项在命名中出现, 默认False, 若为 True, 表示必须输入该参数
    66     # dest —— 把位置或者选项关联到一个特定的名字
    67     parser.add_argument('--port', action="store", dest="port", type=int, required=True)
    68     # 调用parse_args()方法进行解析
    69     given_args = parser.parse_args()
    70     port = given_args.port
    71     echo_server(port)
    72 
    73 def bind(self, address):  # real signature unknown; restored from __doc__
    74     """
    75     bind(address)
    76 
    77     Bind the socket to a local address.  For IP sockets, the address is a
    78     pair (host, port); the host must refer to the local host. For raw packet
    79     sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])
    80     """
    81     pass
    82 def listen(self, backlog=None):  # real signature unknown; restored from __doc__
    83     """
    84     listen([backlog])
    85 
    86     Enable a server to accept connections.  If backlog is specified, it must be
    87     at least 0 (if it is lower, it is set to 0); it specifies the number of
    88     unaccepted connections that the system will allow before refusing new
    89     connections. If not specified, a default reasonable value is chosen.
    90     """
    91     pass
    服务器端代码

    (2)客户端及对应代码解释

     1 # ! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # 编写回显客户端
     4 
     5 import socket
     6 import sys
     7 import argparse
     8 
     9 host = 'localhost'
    10 
    11 
    12 def echo_client(port):
    13     # 创建TCP socket连接
    14     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    15     # 获取服务器端host和端口号
    16     server_address = (host, port)
    17     print("Connecting to %s port %s" % server_address)
    18     sock.connect(server_address)
    19     
    20     try:
    21         # 将message内容发送到服务器端
    22         message = "Test message, This will be echoed"
    23         print("Sending %s" % message)
    24         # python2和python3此处不同
    25         # python2—— sock.sendall(message)
    26         # sendall()发送完整的TCP数据,成功返回None,失败抛出异常
    27         sock.sendall(message.encode())
    28         
    29         # 服务器端将发送的数据回传给客户端并打印
    30         amount_received = 0
    31         amount_expected = len(message)
    32         while amount_received < amount_expected:
    33             data = sock.recv(1024)
    34             amount_received += len(data)
    35             print("Received: %s" % data)
    36     # 处理相对应错误
    37     except socket.error as e:
    38         print("socket error: %s" % str(e))
    39     except Exception as e:
    40         print("Other exception: %s" % str(e))
    41     finally:
    42         print("Closing connection to the server")
    43         sock.close()
    44 
    45 if __name__ == '__main__':
    46     parser = argparse.ArgumentParser(description='Socket Server Example')
    47     parser.add_argument('--port', action="store", dest="port", type=int, required=True)
    48     given_args = parser.parse_args() 
    49     port = given_args.port
    50     echo_client(port)
    客户端代码

     (3)运行结果

     1 1. 服务器端
     2 Abel$ python3 1_13a_echo_server.py --port=9900
     3 Starting up echo server on localhost port 9900
     4 Waiting to receive message from client
     5 
     6 2.客户端发送数据时,服务器端
     7 Data: b'Test message, This will be echoed'
     8 sent b'Test message, This will be echoed' bytes back to ('127.0.0.1', 62389)
     9 Waiting to receive message from client
    10 
    11 3.客户端
    12 Abel$ python3 1_13b_echo_client.py --port=9900
    13 Connecting to localhost port 9900
    14 Sending Test message, This will be echoed
    15 Received: b'Test message, This will be echoed'
    16 Closing connection to the server
  • 相关阅读:
    Arm的几种工作模式
    Linux 串口驱动初始化前置定位crash log
    GPS的经纬度格式及转换
    git 常用命令
    windows 下 mongodb studio 3t 破解无限使用脚本
    从头开始 一、第一天
    十九、IDEA的pom文件手动添加依赖
    十八、{ "a", "ab", "ac", "abc", "de", "bc", "e" }不使用Arrays.sort()进行排序
    十七、Java中数组常见的几种排序方法!
    十六、IDEA创建一个maven工程
  • 原文地址:https://www.cnblogs.com/ouyangyixuan/p/5906346.html
Copyright © 2011-2022 走看看