我有一个用Python语言编写的多进程UDP服务器(参见下面的代码).它会正确地产生所需的进程数量.在Linux上,它在不同进程之间正确地负载平衡UDP数据,但在MacOS上,似乎只有一个进程接收数据.我是不是错过了MacOS的一些参数?

from multiprocessing import Pool
import socket
import os

def s(PORT):
    UDP_IP = ""
    UDP_PORT = PORT

    sock = socket.socket(socket.AF_INET, # Internet
                        socket.SOCK_DGRAM) # UDP
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
    sock.bind((UDP_IP, UDP_PORT))
    print(f"Started server {os.getpid()}")

    while True:
        data, addr = sock.recvfrom(1024)
        print(f"Received message on {os.getpid()}: {data}")

if __name__ == '__main__':
    print(f"Program started {os.getpid()}")
    with Pool(5) as p:
        p.map(s, [8000] * 5)
(Output MacOS)

Program started 32205
Started server 32233
Started server 32235
Started server 32234
Started server 32232
Started server 32236
Received message on 32233: b'hello 1'
Received message on 32233: b'hello 2'
Received message on 32233: b'hello 3'
Received message on 32233: b'hello 4'
Received message on 32233: b'hello 5'
Received message on 32233: b'hello 6'
Received message on 32233: b'hello 7'
Received message on 32233: b'hello 8'
Received message on 32233: b'hello 9'
Received message on 32233: b'hello 10'
(Output Linux)

Program started 1860163
Started server 1860165
Started server 1860164
Started server 1860166
Started server 1860167
Started server 1860168
Received message on 1860167: b'hello 1'
Received message on 1860165: b'hello 2'
Received message on 1860167: b'hello 3'
Received message on 1860167: b'hello 4'
Received message on 1860164: b'hello 5'
Received message on 1860168: b'hello 6'
Received message on 1860164: b'hello 7'
Received message on 1860167: b'hello 8'
Received message on 1860167: b'hello 9'
Received message on 1860164: b'hello 10'

我也try 了SO_REUSEADDR,但它只启动了一个进程.我猜其他进程正在等待BIND完成,但第一个进程已经掌握了它.

我也try 过用Gingicorn守护进程,但同样的问题也存在,即只有一个工人接收数据.

以下是该程序的一个更简单的版本,带有Gunicorn.

# run with 'gunicorn udp_server --reuse-port -w 5'
import socket
import os

UDP_IP = ""
UDP_PORT = 8001

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
sock.bind((UDP_IP, UDP_PORT))
print(f"Process started {os.getpid()}")

while True:
    data, addr = sock.recvfrom(1024)
    print(f"Received message ({os.getpid()}): {data}")

Extra:发送UDP数据

for i in `seq 100`; do echo -n "hello $i" | nc -u -w 1 127.0.0.1 8000; done

推荐答案

不要创建5个不同的套接字.在父进程中创建一个套接字,它将由子进程继承.

from multiprocessing import Pool
import socket
import os

def s(sock):
    while True:
        data, addr = sock.recvfrom(1024)
        print(f"Received message on {os.getpid()}: {data}")

if __name__ == '__main__':
    print(f"Program started {os.getpid()}")
    UDP_IP = ""
    UDP_PORT = 8000

    sock = socket.socket(socket.AF_INET, # Internet
                        socket.SOCK_DGRAM) # UDP
    sock.bind((UDP_IP, UDP_PORT))
    print(f"Started server {os.getpid()}")
    with Pool(5) as p:
        p.map(s, [sock] * 5)

Python相关问答推荐

使用regex分析具有特定字符的字符串(如果它们存在)

symy.分段使用numpy数组

在Python和matlab中显示不同 colored颜色 的图像

在Pandas 日历中插入一行

多处理代码在while循环中不工作

@Property方法上的inspect.getmembers出现意外行为,引发异常

如何根据参数推断对象的返回类型?

Python中的嵌套Ruby哈希

通过Selenium从页面获取所有H2元素

Python键入协议默认值

如何使用pytest来查看Python中是否存在class attribution属性?

在pandas中使用group_by,但有条件

如何在turtle中不使用write()来绘制填充字母(例如OEG)

Python列表不会在条件while循环中正确随机化'

在www.example.com中使用`package_data`包含不包含__init__. py的非Python文件

干燥化与列姆化的比较

Python日志(log)模块如何在将消息发送到父日志(log)记录器之前向消息添加类实例变量

统计numpy. ndarray中的项目列表出现次数的最快方法

使用tqdm的进度条

python的文件. truncate()意外地没有截断'