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?