RPC 笔记(08)— socket 通信(多进程多线程服务器)

news/2025/2/16 5:10:45/

在上一节中如果并行的客户端连接数超过了默认开启进程的数量,那么后来的客户端请求将会阻塞,为了不阻塞新的客户端,我们可以将进程的单线程改成多线程即可。

服务端代码:

import json
import struct
import socket
import threading
import multiprocessingdef 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 multi_thread(sock, handlers):threads = []thread_nums = 2for i in range(thread_nums):t = threading.Thread(target=process_request, args=(sock, handlers))threads.append(t)for i in range(thread_nums):threads[i].start()for i in range(thread_nums):threads[i].join()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)  # 进入服务循环process = []process_nums = 2for i in range(process_nums):p = multiprocessing.Process(target=multi_thread, args=(s, handlers))process.append(p)for i in range(process_nums):process[i].start()for i in range(process_nums):process[i].join()if __name__ == '__main__':main()

示例代码中开启 2 个进程,每个进程中又开了 2 个线程,那么此时最多可以同时开启 4 个客户端,超过 4 个客户端后多余的请求会被阻塞处理。


http://www.ppmy.cn/news/603121.html

相关文章

Pyinstaller 打包 torch 后执行失败 OSError: could not get source code

1. 问题现象 系统环境 Python 3.6.9torch 1.2.0torchvision 0.4.0Pyinstaller 4.5.1 Pyinstaller 打包 torch 后执行失败 OSError: could not get source code 。 Traceback (most recent call last):File "main.py", line 29, in <module>File "<…

ERROR: Failed compiling the bootloader. Please compile manually and rerun setup.py

1. 问题现象 在使用 pip 安装 pyinstaller 时&#xff0c;有如下错误 $ sudo pip3 install pyinstaller4.5.1 -i https://pypi.douban.com/simple/Collecting pyinstaller4.5.1Downloading https://pypi.doubanio.com/packages/a9/d9/9fdfb0ac2354d059e466d562689dbe53a23…

pip 无法卸载 pillow 解决方案 Not uninstalling pillow at /usr/lib/python3/dist-packages

1. 问题现象 使用 pip 卸载 pillow 时无法卸载&#xff0c;报如下错误&#xff1a; $ sudo pip3 uninstall pillow Not uninstalling pillow at /usr/lib/python3/dist-packages, outside environment /usr2. 解决方法 sudo apt remove python3-pil或者 sudo apt remove…

使用 Go module 后 VScode 智能提示不生效解决方案

关闭 Use Language Server 如果你对这个选项有打钩先取消&#xff0c;然后重启 vscode 。 安装 gocode go install github.com/stamblerre/gocodelatest参考 https://www.icode9.com/content-4-719446.html https://blog.csdn.net/richard_m_yang/article/details/100516891…

Docker 常见问题 — 配置国内镜像源、备份本机所有镜像文件、批量清理临时镜像文件、删除所有本地镜像、镜像默认存放路径、

1. 配置国内镜像源 由 Docker 官方提供的国内镜像源&#xff1a; registry.docker-cn.com在 Linux 环境下&#xff0c;我们可以通过修改 /etc/docker/daemon.json ( 如果文件不存在&#xff0c;直接创建它 ) 这个 Docker 服务的配置文件达到效果。 {"registry-mirrors&…

Go 学习笔记(82)— Go 第三方库之 viper(解析配置文件、热更新配置文件)

1. viper 特点 viper 是一个完整的 Go应用程序的配置解决方案&#xff0c;它被设计为在应用程序中工作&#xff0c;并能处理所有类型的配置需求和格式。支持特性功能如下&#xff1a; 设置默认值读取 JSON、TOML、YAML、HCL、envfile和 Java属性的配置文件监控配置文件改动&a…

Go 知识点(18)— 条件编译(编译标签、文件后缀)

1. 条件编译 Go 能根据所处环境选择对应的源码进行编译。让编译器只对满足条件的代码进行编译&#xff0c;将不满足条件的代码舍弃&#xff0c;这就叫做条件编译。 在 Go 中&#xff0c;也称之为 Build Constraints 编译约束&#xff0c;添加编译约束的以下 2 种&#xff1a;…

Go 知识点(19)— Go 语言中的野指针

野指针是一种指向内存位置是不可知的指针&#xff0c;一般是由于指针变量在声明时没有初始化所导致的。在 Go语言中&#xff0c;布尔类型的零值为 false&#xff0c;数值类型的零值为 0&#xff0c;字符串类型的零值为 ""&#xff0c;而指针、切片、映射、信道、函数…