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

标签 c linux sockets udp pcap

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

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

我尝试使用pcap来做到这一点,但有时似乎丢失了一些数据包。(服务器将向客户端发送一些视频流)

最佳答案

如果您想在服务器进程上使用单个 send/sendto 来执行此操作,则需要使用多播。为了简洁起见/重用我现有的代码,这里是用 Python 2.7.x 完成的快速示例。

如果您打算在同一主机上运行发送器和接收器时使用此方法,则发送端设置 IP_MULTICAST_LOOP 非常重要。

发件人.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) 

接收者.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, ...) for X={setsockopt, bind , 发送, 接收}
  3. 请参阅有关 ip_mreq 的注释。

关于c - 2个程序从端口获取相同的udp数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39276951/

相关文章:

c - 如何让 system() 使用通配符

c - c中哈希表的查找函数?

linux - 用于图书馆的软件中心 Ubuntu

linux - 如何过滤巨大的日志文件以仅包含有用的消息

javascript - 编辑 Node js文件而无需重新启动服务器

c - 为什么 fmax(a, b) 返回较小的(负)零以及如何干净地解决它?

c - 在 libgit2 中使用 SSH 身份验证

linux - 如何将现有 Linux VM 克隆到 Azure 中的规模集

c++ - 如何确定 C++ 中的 IP 版本?

c++ - 什么时候需要修改socket的接收缓冲区大小?