多线程 TCP 套接字服务器

当没有参数运行时,该程序启动一个 TCP 套接字服务器,该服务器侦听端口 5000 上与 127.0.0.1 的连接。服务器在单独的线程中处理每个连接。

使用 -c 参数运行时,此程序将连接到服务器,读取客户端列表并将其打印出来。客户端列表作为 JSON 字符串传输。可以通过传递 -n 参数来指定客户端名称。通过传递不同的名称,可以观察到对客户列表的影响。

client_list.py

import argparse
import json
import socket
import threading

def handle_client(client_list, conn, address):
    name = conn.recv(1024)
    entry = dict(zip(['name', 'address', 'port'], [name, address[0], address[1]]))
    client_list[name] = entry
    conn.sendall(json.dumps(client_list))
    conn.shutdown(socket.SHUT_RDWR)
    conn.close()

def server(client_list):
    print "Starting server..."
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('127.0.0.1', 5000))
    s.listen(5)
    while True:
        (conn, address) = s.accept()
        t = threading.Thread(target=handle_client, args=(client_list, conn, address))
        t.daemon = True
        t.start()

def client(name):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('127.0.0.1', 5000))
    s.send(name)
    data = s.recv(1024)
    result = json.loads(data)
    print json.dumps(result, indent=4)

def parse_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', dest='client', action='store_true')
    parser.add_argument('-n', dest='name', type=str, default='name')
    result = parser.parse_args()
    return result

def main():
    client_list = dict()
    args = parse_arguments()
    if args.client:
        client(args.name)
    else:
        try:
            server(client_list)
        except KeyboardInterrupt:
            print "Keyboard interrupt"

if __name__ == '__main__':
    main()

服务器输出

$ python client_list.py
Starting server...

客户输出

$ python client_list.py -c -n name1
{
    "name1": {
        "address": "127.0.0.1", 
        "port": 62210, 
        "name": "name1"
    }
}

接收缓冲区限制为 1024 字节。如果客户端列表的 JSON 字符串表示超出此大小,则将截断该表示。这将导致引发以下异常:

ValueError: Unterminated string starting at: line 1 column 1023 (char 1022)