通过 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)。
应用多进程多线程模型
一直疑惑一个应用app如何才能以多进程,多线程的方式运行。对于多线程可能很好理解,我们只要在进程中启用多线程的模式即可。也就是来一个请求,我们就用函数pthread_create()启用一个线程即可。这样我们的应用就可以在单进程,多线程的模式下工作。
一个应用app通常工作在多进程,多线程的模式下,它的效率是最高的。那么我们如何才能做到多进程模式呢?经验告诉我们,如果多次启动一个进程会报错:“Address already in use!"。这是由于bind函数导致的,由于该端口号已经被监听了。
fork原理
fork时,子进程复制一份父进程的资源。然后父子进程分别执行os.fork()之后的程序
子进程中fork函数返回0,父进程中返回子进程的pid
Python的os.fork()是一个会返回两次的函数
通过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
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服务网络策略是否正常时,可以使用到 ...
随机推荐
NOIP 考前 数论复习
POJ 2891 x=r1 (mod a1) x=r2 (mod a2) x=a1*x+r1,x=a2*y+r2; a1*x-a2*y=r2-r1; 用Extend_Gcd求出m1*x+m2*y=d; ...
mysql数据库字符集的设置
my.ini文件中clinet和mysqld中的写法不一样,要注意 [client] port=3306 default-character-set=utf8 [mysqld] ...
csuoj 1503: 点到圆弧的距离
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1503 1503: 点到圆弧的距离 时间限制: 1 Sec 内存限制: 128 MB Speci ...
(1)java虚拟机概念和结构图
java虚拟机解构图一 java虚拟机解构图二 java虚拟机结构图三 [1]类加载系统 --->负责从文件系统或网络中加载class信息,存放至方法区的内存空间[2]java堆 ...
深入了解epoll (转)
一. 介绍 Epoll 是一种高效的管理socket的模型,相对于select和poll来说具有更高的效率和易用性.传统的select以及poll的效率会因为 socket数量的线形递增而导致呈二次乃 ...
candy(动态规划)
题目描述 There are N children standing in a line. Each child is assigned a rating value. You are giving ...
Java六大必须理解的问题
Java六大必须理解的问题 对于这个系列里的问题,每个学Java的人都应该搞懂.当然,如果只是学Java玩玩就无所谓了.如果你认为自己已经超越初学者了,却不很懂这些问题,请将你自己重归初学者行列.内容 ...
纯CSS打造萌萌哒大白
HTML部分:
BeautifulSoup4----利用find_all和get方法来获取信息
中文文档 官方教学网页源码:
Page titlejQuery设置内容和属性方
何问起 hovertree.com 设置内容 - text().html() 以及 val()text() - 设置或返回所选元素的文本内容html() - 设置或返回所选元素的内容(包括 HTML ...