有一个服务器会向我的localhost发送一些UDP数据包,例如:如果它向我的localhost发送一些UDP数据包,目标端口是5000.并且将有一个客户端程序在端口5000上接收它。但是,我想要的是创建另一个程序,它将尝试在端口5000上接收相同的数据包。
如果服务器将数据包p1,p2,p3 .... pn发送到我的localhost端口5000,我希望两个客户端程序都会收到相同的数据包。 (客户端程序1:p1,p2,p3 .... pn,客户端程序2:p1,p2,p3 ... pn)
我尝试使用pcap执行此操作,但有时会丢失一些数据包。(服务器会向客户端发送一些视频流)
答案 0 :(得分:2)
如果要在服务器进程上使用单个send
/ sendto
执行此操作,则需要使用多播。以下是在Python 2.7.x中完成的快速示例,为了简化/重用我已经存在的代码。
如果您要将此方法与发射器和放大器一起使用,则设置IP_MULTICAST_LOOP
的发送方是导入的。接收器在同一主机上运行。
sender.py:
#!/usr/bin/env python
import socket
import sys
MCAST_GROUP=sys.argv[1]
MCAST_PORT=int(sys.argv[2])
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt( socket.SOL_SOCKET, socket.IP_MULTICAST_LOOP, 1 )
for ii in xrange(10):
msg = 'message %d' %ii
print 'sending: "%s"' %msg
s.sendto( msg, (MCAST_GROUP, MCAST_PORT)
receiver.py:
#!/usr/bin/env python
import socket
import sys
import struct
MCAST_GROUP=sys.argv[1]
MCAST_PORT=int(sys.argv[2])
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
s.bind( (MCAST_GROUP, MCAST_PORT) )
# In C, you'll want to use struct ip_mreq here. See 'man 7 ip' for details.
# Python's socket module doesn't define a convenient way to do this, hence the
# 'manual' struct.pack
mreq = struct.pack( '4sI', socket.inet_aton(MCAST_GROUP), socket.INADDR_ANY )
s.setsockopt( socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq )
while True:
rx_data = s.recv(1000)
print 'received: "%s"' %rx_data
两个程序都需要两个命令行参数,一个IPv4多播IP(224.0.0.0 - 239.255.255.255)和一个端口。例如(./sender.py 239.10.10.10 5000
)。
您应该可以在不同的终端中运行任意数量的receiver.py
实例,并看到sender.py
的单个实例将传输到所有接收者。
要将其翻译为C
,基本上是:
s = socket.socket(...)
- > s = socket(...)
s.X(...)
转换为X(s, ...)
,表示X = {setsockopt
,bind
,send
,recv
} ip_mreq
。答案 1 :(得分:1)
在套接字上读取/ recv后,消息将从套接字消失,因此即使您使用SO_REUSEADDR / SO_REUSEPORT,我也不认为您将能够读取两个客户端的数据包。
我认为最简单的选择是在端口5000上运行本地服务,然后将所有数据包转发到其他服务。无论您将其写为服务器发布/子样式还是硬编码,都可能需要根据您想要投入多少精力来决定。