多執行緒 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)