2

there is a server will send some UDP packets to my localhost, for example: if it send some UDP packets to my localhost and destination port is 5000. and there will have a client program to receive it on port 5000. but, what I want is to create another program, it will try to receive the same packets on port 5000.

if the server send packets p1, p2, p3....pn to my localhost port 5000, I want to both client programs will receive same packets. (client program 1: p1, p2, p3....pn, client program 2: p1, p2, p3...pn)

I tried to use pcap to do this, but seems lost some packets in sometimes.(the server will send some video stream to client)

1
  • iptables would do the trick without any extra coding. ask at unix.stackexchange.com Commented Sep 1, 2016 at 16:54

2 Answers 2

3

You need to use multicast if you want to do this with a single send / sendto on the server process. Here are quick examples done in Python 2.7.x for the sake of brevity / reuse of code I had laying around.

It's import for the transmit side to set IP_MULTICAST_LOOP if you are going to use this method with transmitter & receivers running on the same host.

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

Both programs expect two command line arguments, an IPv4 multicast IP (224.0.0.0 - 239.255.255.255), and a port. For example (./sender.py 239.10.10.10 5000).

You should be able to run as many instances of receiver.py as you like in different terminals, and see that a single instance of sender.py will transmit to all receivers.

To translate this to C, it's basically:

  1. Convert s = socket.socket(...) -> s = socket(...)
  2. Convert s.X(...) to X(s, ...) for X={setsockopt, bind, send, recv}
  3. See notes about ip_mreq.
Sign up to request clarification or add additional context in comments.

Comments

1

Once you read/recv on the socket the messages will be gone from the socket, so even if you use SO_REUSEADDR/ SO_REUSEPORT, I don't think you will be able to read the packets with both clients.

I think the easiest option is to have a local service running on port 5000 which then forwards all packets to the other services. Whether you write that as a server pub/sub style or hard-code it is probably something to decide based on how much effort you want to put into this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.