多线程 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)