1. 客户端代码
import json
import time
import struct
import socketdef send_request(sock_obj, method, parameter):request = json.dumps({"client": method, "params": parameter}) # 请求消息体length_prefix = struct.pack("I", len(request)) # 请求长度前缀print("request is {}".format(str.encode(request)))sock_obj.sendall(length_prefix)# sock.sendall(request) python2sock_obj.sendall(str.encode(request)) # python3def receive_response(sock_obj):length_prefix = sock_obj.recv(4) # 响应长度前缀length, = struct.unpack("I", length_prefix)# print("length is {}".format(length))body = sock_obj.recv(length) # 响应消息体res = json.loads(body)return res # 返回响应if __name__ == '__main__':s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect(("localhost", 8080))for i in range(10):send_request(s, "func1", "I am {} message".format(i))response = receive_response(s)print("response is {}".format(response))time.sleep(1)s.close()
2. 服务端代码
import json
import struct
import socket
import threadingdef handle_conn(conn, ip, handlers):print("{} connect ...".format(ip))# 循环读写while True:length_prefix = conn.recv(4) # 请求长度前缀if not length_prefix: # 连接关闭了conn.close()print("{} close ...".format(ip))break # 退出循环,处理下一个连接length, = struct.unpack("I", length_prefix)body = conn.recv(length) # 请求消息体request = json.loads(body)client_method = request['client']client_parameter = request['params']print("client request method is {}, params is {}".format(client_method, client_parameter))handler = handlers[client_method] # 查找请求处理器handler(conn, client_parameter) # 处理请求def process_request(sock, handlers):while True:conn, host_ip = sock.accept() # 接收连接handle_conn(conn, host_ip, handlers) # 处理连接def func1(conn, params):res = json.dumps({"response": "OK", "result": params}) # 响应消息体length_prefix = struct.pack("I", len(res)) # 响应长度前缀conn.sendall(length_prefix)# conn.sendall(response) # python2conn.sendall(str.encode(res)) # python3def main():s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建一个 TCP 套接字s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 打开 reuse addr 选项s.bind(("localhost", 8080)) # 绑定端口s.listen(1) # 监听客户端连接handlers = {"func1": func1 # 注册请求处理器}# process_request(s, handlers) # 进入服务循环threads = []thread_nums = 3for i in range(thread_nums):t = threading.Thread(target=process_request, args=(s, handlers))threads.append(t)for i in range(thread_nums):threads[i].start()for i in range(thread_nums):threads[i].join()if __name__ == '__main__':main()
服务端开了 3 个线程用于处理客户端请求,此时如果客户端数量小于等于 3时,服务端会并行处理,如果客户端数量大于 3 服务端则会阻塞,直到有之前连接的客户端断开,才会继续处理。