Using SO_REUSEPORT to simulate stateful UDP

567 views Asked by At

I am building a p2p application in which every peer can maintain a connection with multiple other peers.

Maintaining a connection is easy with TCP. I have a server listening on a specific port on every node. Whenver peerA wants to connect to peerB, it creates a socket and makes a connect call to the listening port of peerB. This creates a new socket on which both the peers can do all their subsequent conversation on.

I want to simulate the same concept of workflow in UDP. Something similar to this question The traditional way of conversing with multiple peers on UDP from what I found is that every peer is listening on a predefined port. Every sendTo call specifies the ip and port of the peer we want to connect to and on the receiver side, we use recvFrom to handle it based on which peer it is coming from (e.g. passing the msg to a thread which handles messages from that specific peer).

However, I wanted to know if there is any way of doing the same without the need to demultiplex at the receiver. I found the SO_REUSEPORT flag can be used to implement this http://man7.org/linux/man-pages/man7/socket.7.html

https://lwn.net/Articles/542629/.

Basically, SO_REUSEPORT allows multiple sockets call bind on the same port. So, I bind a server port similarly as before. However, when I get a connection from a new peer, I bind a new socket to the same port and call connect on the sender's address. Then I pass this new socket to a thread which listens to messages from the sender.

makeListeningSocket ip port = do
  sock <- socket ip port
  setSocketOption sock ReusePort 1
  bind sock
  return sock

runUDPServer sock = do
  (receivedMessage, peerAddr) <- recvFrom sock 4096
  newSock <- makeListeningSocket "0.0.0.0" 3001
  connect newSock peerAddr
  async (readMessagesFromSock newSock)
  runUDPServer sock

I was able to make this approach work. However, SO_REUSEPORT option doesn't seem to be created with this specific use case in mind. So my question is, is there anything horribly wrong with using SO_REUSEPORT in this manner which I am not able to see? Are there better ways of doing this?

0

There are 0 answers