1

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?

pd176
  • 821
  • 3
  • 10
  • 20
  • TCP is a _connection-oriented_ protocol, but UDP is a _connectionless_ protocol. If you want connections with UDP, you must implement that in your application. TCP takes care of that for you, but UDP does not, and you need to build connection functionality into the application. – Ron Maupin Jun 26 '18 at 15:15
  • @RonMaupin I don't want any of the reliability guarantees of TCP. Just wanted to see if I can simulate the accepting on a socket and all subsequent communication between peers on that socket workflow of TCP in UDP as well – pd176 Jun 26 '18 at 15:20
  • TCP, itself, creates and maintains connections, but UDP does not. UDP is a best-effort, fire-and-forget protocol. If you want connections with UDP, you must do that yourself. – Ron Maupin Jun 26 '18 at 15:21
  • @RonMaupin I understand that. Just wanted to know if my way of maintaining connections with UDP has any blatant flaws – pd176 Jun 26 '18 at 15:25
  • This obviously is not portable, so you'll either have to stick to linux or test on additional platforms. Secondly, I vaguely recall the behavior being changed after that socket option was introduced, but maybe that was on a different platform. So you may or may not run into trouble on older kernels. – the8472 Jun 28 '18 at 19:09

0 Answers0