5

The problem is that there are two processes:

  1. Process A knows only to send.
  2. Process B knows only to receive.

And process C is a compiled binary so it cannot be changed.

Process C has to receive from A and send to B. I bind process B to port X. Since process A always sends each time from different random port and process C answers it to these ports, process B never get data.

Currently my solution:

  • Bind process B to listen on port X (using reuse)
  • Bind process A to send from port X (using reuse)
  • Always start first A and than B.

This solution works, but inconsistently.

So the question is: Is there a possibility to send to localhost UDP packet from specific port without bind to it? Maybe some other solution?

Here is a diagram for current state:

enter image description here

5
  • I don't think there's any way to set the source port except with bind(). Why can't A send directly to B? Commented Jun 27, 2013 at 7:27
  • 1
    Oh, I get it. C is the server -- it does something with the message that A sends, but you want replies to go to B rather than A. But C doesn't know that it's talking to two different processes. Commented Jun 27, 2013 at 7:31
  • Yes. Thats exactly the problem. Commented Jun 27, 2013 at 7:40
  • If A and B are running on the same PC, then perhaps you can have A use a RAW socket instead of a UDP socket so that it can create the UDP header manually and forge the sender Port to match what B is listening on. Commented Jun 27, 2013 at 8:12
  • If you specify the IP_HDRINCL option on a RAW socket, then you can manually create the IP header as well, which should allow for forging the sender IP if A and B are not running on the same PC. Commented Jun 27, 2013 at 8:22

1 Answer 1

5

Start A and B from a single parent process. The parent process creates the socket and binds it to port X. Then it forks, and the child process inherits this socket. One of the processes then executes A, the other executes B. The FD of the socket can be passed to them in argv.

The reason SO_REUSEPORT doesn't work reliably is because each socket has its own input queue. When a datagram arrives on the port, the OS picks one of the sockets and puts the message on its queue. If it picks the socket used by A, B won't see that message. I don't think there's a way to tell the OS that one of the sockets is only intended for sending, not receiving.

Using the inherited socket solve this problem because it's just a single socket, so there's just one queue. Whichever process calls recv() will get all the messages.

Sign up to request clarification or add additional context in comments.

7 Comments

I understand what you are saying. Will this work if I bind socket to this port in process A and than using IPC messaging to pass FD to process B?
Yes, that's another way of accomplishing the same thing.
"I don't think there's a way to tell the OS that one of the sockets is only intended for sending, not receiving." what about using shutdown(SHUT_RD) to close the inbound portion of the socket while leaving the outbound portion open?
What worked for me is creating socket in process A and binding it to port 2222, than started process B using fork from A and passed it FD of bound socket. Than I just used that FD in recv of process B.
Could you please have a look on my question ? stackoverflow.com/questions/41192809/…
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.