2程序从端口获取相同的udp数据包

时间:2016-09-01 16:51:01

标签: c linux sockets udp pcap

有一个服务器会向我的localhost发送一些UDP数据包,例如:如果它向我的localhost发送一些UDP数据包,目标端口是5000.并且将有一个客户端程序在端口5000上接收它。但是,我想要的是创建另一个程序,它将尝试在端口5000上接收相同的数据包。

如果服务器将数据包p1,p2,p3 .... pn发送到我的localhost端口5000,我希望两个客户端程序都会收到相同的数据包。 (客户端程序1:p1,p2,p3 .... pn,客户端程序2:p1,p2,p3 ... pn)

我尝试使用pcap执行此操作,但有时会丢失一些数据包。(服务器会向客户端发送一些视频流)

2 个答案:

答案 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,基本上是:

  1. 转换s = socket.socket(...) - > s = socket(...)
  2. s.X(...)转换为X(s, ...),表示X = {setsockoptbindsendrecv}
  3. 请参阅有关ip_mreq
  4. 的说明

答案 1 :(得分:1)

在套接字上读取/ recv后,消息将从套接字消失,因此即使您使用SO_REUSEADDR / SO_REUSEPORT,我也不认为您将能够读取两个客户端的数据包。

我认为最简单的选择是在端口5000上运行本地服务,然后将所有数据包转发到其他服务。无论您将其写为服务器发布/子样式还是硬编码,都可能需要根据您想要投入多少精力来决定。