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服务网络策略是否正常时,可以使用到 ...
随机推荐
- learning java StringBuilder 类
StringBuilder s1 = new StringBuilder(); s1.append("panzidong"); s1.insert(,"hong,&quo ...
- noi.ac #45 计数
\(des\) 给定 \(n\) 的全排列 + 一个值域属于 \([1, n]\) 的元素构成长度为 \(n + 1\) 的序列 问长度为 \(i\) 的本质不同的子序列的个数 \(sol\) 小学计 ...
- AtCoder Grand Contest 006 题解
传送门 \(A\) 咕咕 const int N=105; char s[N],t[N];int n; inline bool eq(R int k){fp(i,1,k)if(s[n-k+i]!=t[ ...
- Luogu4931 情侣?给我烧了!(加强版)【生成函数】
题目链接:洛谷 大家一起 日 ♂ % EI 设\(D_i\)表示\(k=0\)时的答案.那么 \[ f(n,k)=\binom{n}{k}^2D_{n-k}k!2^k \] 意义是选择\(k\)对情侣 ...
- P2502 [HAOI2006]旅行——暴力和并查集的完美结合
P2502 [HAOI2006]旅行 一定要看清题目数据范围再决定用什么算法,我只看着是一个蓝题就想到了记录最短路径+最小生成树,但是我被绕进去了: 看到只有5000的边,我们完全可以枚举最小边和最大 ...
- Editorial of Codeforces Round #572
技不如人啊emmm A \(f_{i}\)表示前\(i\)个最小割段,顺便用\(pre_{i}\)记录上一个转移过来的位置 B 这题似乎随便乱搞都能过 官方题解:\(a_{n-1},a_n,a_{n- ...
- tecplot三维模型绘制二维切片流线
原视频下载地址链接: https://pan.baidu.com/s/1csugHK 密码: xrni
- cmake和json安装
一.cmake源码安装 官网下载源码:https://cmake.org/download/ 安装: ./bootstrap make make install cmake --version 二.j ...
- 和小哥哥一起刷洛谷(4) 图论之广度优先搜索BFS
关于bfs: 你怎么会连这个都不知道!!!自己好好谷歌一下!!!(其实我也刚学) bfs伪代码: while(队列非空){ 取出队首元素u; 弹出队首元素; u染色为黑色; for(int i=0;i ...
- 【转】Linux 利用 PROMPT_COMMAND 实现审计功能
linux历史命令记录在history,在用户退出的时候写入,不过有时候可以直接绕过去,不让写入,比如shutdown now,还有在一些情况下也是不予保存的,这让人很头疼 使用PROMPT_COMM ...