linux系统实现多个进程监听同一个端口
通过 fork 创建子进程的方式可以实现父子进程监听相同的端口。
方法:在绑定端口号(bind函数)之后,监听端口号之前(listen函数),用fork()函数生成子进程,这样子进程就可以克隆父进程,达到监听同一个端口的目的。
# 代码示例:一主一子
import socket
import select
import sys
import struct
import os
import time
if __name__ == '__main__':
pid = os.getpid()
s1 = socket.socket() # 创建 socket 对象
# host = socket.gethostname() # 获取本地主机名
host = '127.0.0.1'
port1 = 12346 # 设置端口号
# port2 = 12347
# --关键代码--
s1.bind((host, port1))
pid1 = os.fork()
print("我会被主子进程分别执行一次")
# 也可以分别写到分子进程里
s1.listen(5)
# --关键代码--
while True:
if pid1 == 0:
# s1.listen(5)
print("子进程")
socket1, addr1 = s1.accept()
print(addr1)
socket1.send("子进程响应".encode('utf-8'))
socket1.close()
print('结束服务端子进程')
else:
# s1.listen(5)
print("主进程")
socket2, addr2=s1.accept()
print(addr2)
socket2.send("主进程响应".encode('utf-8'))
socket2.close()
print('结束服务端主进程')
# 代码示例:一主多子
import socket
import select
import sys
import struct
import os
import time
if __name__ == '__main__':
pid = os.getpid()
s1 = socket.socket() # 创建 socket 对象
# host = socket.gethostname() # 获取本地主机名
host = '127.0.0.1'
port1 = 12346 # 设置端口号
# port2 = 12347
s1.bind((host, port1))
pid1 = os.fork()
# s1.listen(5)
print("我会被主子进程分别执行一次")
while True:
if pid1 == 0:
s1.listen(5)
print("子进程1")
socket1, addr1 = s1.accept()
print(addr1)
socket1.send("子进程响应1".encode('utf-8'))
socket1.close()
print('结束服务端子进程1')
elif pid1 != 0:
pid2 = os.fork()
if pid2 == 0:
s1.listen(5)
print("子进程2")
socket2, addr2 = s1.accept()
print(addr2)
socket2.send("子进程响应2".encode('utf-8'))
socket2.close()
print('结束服务端子进程2')
else:
s1.listen(5)
print("主进程")
socket2, addr2 = s1.accept()
print(addr2)
socket2.send("主进程响应".encode('utf-8'))
socket2.close()
print('结束服务端主进程')
# 试想下子进程还有子进程的写法和用法
惊群现象
当连接到来时,子进程、父进程都可以 accept, 这就是著名的“惊群”问题(thundering herd problem)。
在该模型下(多个子进程同时共享监听套接字)即可实现服务器并发处理客户端的连接。这里要注意的是,计算机三次握手创建连接是在内核进程里完成的,不需要应用服务进程参数的,而服务进程仅仅要做的是调用accept将已建立的连接构建对应的连接套接字connfd(可参考 http://blog.csdn.net/ordeder/article/details/21551567)。多个服务进程同时阻塞在accept等待监听套接字已建立连接的信息,那么当内核在该监听套接字上建立一个连接,那么将同时唤起这些处于accept阻塞的服务进程,从而导致“惊群现象”的产生,唤起多余的进程将影响服务器的性能(仅有一个服务进程accept成功,其他进程被唤起后没抢到“连接”而再次进入休眠)。
应用多进程多线程模型
一直疑惑一个应用app如何才能以多进程,多线程的方式运行。对于多线程可能很好理解,我们只要在进程中启用多线程的模式即可。也就是来一个请求,我们就用函数pthread_create()启用一个线程即可。这样我们的应用就可以在单进程,多线程的模式下工作。
一个应用app通常工作在多进程,多线程的模式下,它的效率是最高的。那么我们如何才能做到多进程模式呢?经验告诉我们,如果多次启动一个进程会报错:“Address already in use!"。这是由于bind函数导致的,由于该端口号已经被监听了。
fork原理
fork时,子进程复制一份父进程的资源。然后父子进程分别执行os.fork()之后的程序
子进程中fork函数返回0,父进程中返回子进程的pid
Python的os.fork()是一个会返回两次的函数
https://www.cnblogs.com/Magic-Dev/p/11405448.html
通过linux内核的SO_REUSEPORT选项实现多个进程监听相同的端口
# reuseport.py代码
import socket
import os
#xiaorui.cc
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.bind(('0.0.0.0', 1234))
s.listen(1)
while True:
conn, addr = s.accept()
print('Connected to {}'.format(os.getpid()))
data = conn.recv(1024)
conn.send(data)
conn.send(str(os.getpid()))
conn.close()
# 启动多个进程
nohup python reuseport.py &
nohup python reuseport.py &
nohup python reuseport.py &
# 使用nc测试,可以得到随机的一个进程响应
echo "xiaorui" | nc localhost 1234
# 使用socat(nc的增强版)测试,可以得到随机的一个进程响应
echo "ss" | socat - tcp-connect:localhost:1234
http://xiaorui.cc/2015/12/02/使用socket-so_reuseport提高服务端性能/
https://www.jianshu.com/p/7e84a33b46e9
linux系统实现多个进程监听同一个端口的更多相关文章
- linux 系统下开机自动启动oracle 监听和实例 (亲测有效)
[oracle@oracle11g ~]$ dbstartORACLE_HOME_LISTNER is not SET, unable to auto-start Oracle Net Listene ...
- linux: 获取监听指定端口的进程PID
在 linux 下经常需要杀死(重启)监听某端口的进程, 因此就写了一个小脚本, 通过 ss 命令获取监听制定端口的进程 PID, 然后通过 kill 命令结束掉进程: #!/bin/sh # set ...
- [Linux] 多进程网络编程监听一个端口
SO_REUSEPORT支持多个进程或者线程绑定到同一端口 每个进程可以自己创建socket.bind.listen.accept相同的地址和端口,各自是独立平等的.让多进程监听同一个端口,各个进程中 ...
- linux系统中,查看当前系统中,都在监听哪些端口
需求描述: 查看当前系统中都监听着哪些的端口,用netstat命令,在此记录下 操作过程: 1.查看系统中都在监听哪些端口 [root@testvm home]# netstat -ntl Activ ...
- Linux中安装Oracle11g后出现监听的问题及解决办法
软件安装: 参考文章: linux安装Oracle11G 错误如下: [oracle@iz2f570bi1k56uz admin]$ lsnrctl start LSNRCTL for Linux: ...
- Linux下启动Oracle服务和监听程序步骤
Linux下启动Oracle服务和监听程序启动和关闭步骤整理如下: 1.安装oracle: 2.创建oracle系统用户: 3./home/oracle下面的.bash_profile添加几个环境变量 ...
- Linux下的启动oracle服务 启动监听 开放端口操作
尝试登录oracle 使用root用户将没有sqlplus命令 [root@localhost ~]# sqlplus /nolog bash: sqlplus: 未找到命令... [root ...
- 获取Windows下某进程监听的TCP/UDP端口
1.在Windows下用CMD netstat命令可以获得当前进程监听端口号的信息,如netstat -ano可以看到IP.port.状态和监听的PID. 那么可以执行CMD这个进程得到监听的端口号信 ...
- Linux 使用NC命令永久监听本地端口
感谢: 冰点阳光 Linux可以使用nc命令来测试网络端口是否正常,类似于telnet命令,但也可以用nc命令来监听本地端口,支持TCP.UDP协议,当我们测试NTP服务网络策略是否正常时,可以使用到 ...
随机推荐
- Kylin 架构模块简介
Apache Kylin™是一个开源的分布式分析引擎,提供Hadoop/Spark之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据,最初由eBay Inc. 开发并贡献至开源社区.它能 ...
- zabbix sender
在zabbix中自定义一个虚拟主机,自定义key值,一般运用的是自动发现规则,给清单规则中配置上宏变量,通过py脚本调动zabbixsender模块,给这个主机,host发送一组包含键和宏变量的值,这 ...
- 使用apache 的 ab命令压力测试nginx服务器
nginx压力测试方法: #ab命令 #安装ab #Centos系统 yum install apr-util #Ubuntu系统 sudo apt-get install apache2-utils ...
- mysql 索引基本概念
1. 什么是索引? 索引是一种数据结构,可以帮助我们快速的进行数据的查找. 2. 索引是个什么样的数据结构呢? 索引的数据结构和具体存储引擎的实现有关, 在MySQL中使用较多的索引有Hash索引,B ...
- vue-d2admin-axios异步请求登录,先对比一下Jquery ajax, Axios, Fetch区别
先说一下对比吧 Jquery ajax, Axios, Fetch区别之我见 引言 前端技术真是一个发展飞快的领域,我三年前入职的时候只有原生XHR和Jquery ajax,我们还曾被JQuery 1 ...
- ZwQuerySystemInfoMation函数使用
ZwQueryInfoMation函数很简单.就是4个参数. NTSTATUS WINAPI ZwQuerySystemInformation( _In_ SYSTEM_INFORMATION_CLA ...
- 2019.10.25字符串——zr
题意: 给你两个字符串,由01组成:求他们两个的最短公共非子序列,要求字典序最小: 非公共子序列:都不是这两个字符串的子序列: 本人只会暴力啊,二进制枚举稳拿15分: 然而这道题其实是一个最短路题: ...
- vue后台_纯前端实现excel导出/csv导出
之前的文件下载功能一般是由前后端配合实现,由于项目需要,纯前端实现了一把excel的导出功能: 一.excel导出 1.安装依赖库 xlsx:这是一个功能强大的excel处理库,但是上手难度也很大,还 ...
- Anaconda3自带jupyter
1.cmd命令行中输入 JupyterNotebook 2.系统自动调起下面页面(注册端口冲突是打不开的)
- vue+elementui搭建后台管理界面(4使用font-awesome)
使用font-awesome npm install --save font-awesome 修改 src/main.js 增加 import 'font-awesome/scss/font-awes ...