1

I'm trying to implement mainline dht. While implementing I found it easier to use multithreading to handle requests and send requests at the same time. But it's impossible for a singular port to both send and receive at the same time. There's two solutions I thought of, one of those would be using different ports for receiving and sending, however in mainline dht it seems like whenever you send a request, nodes will remember you based on the port you send the request on. Is it possible to still implement a different port for receiving and sending?

raz
  • 29
  • 7

1 Answers1

1

The DHT requires that the same port is used for sending and receiving.

But it's impossible for a singular port to both send and receive at the same time.

Sockets are thread-safe, you can issue send and receive syscalls to the same socket at the same time.

If you want to load-balance reading across multiple threads you can open multiple sockets bound to the same port via SO_REUSEPORT but that shouldn't be necessary because any regular DHT implementation will only see a dozen packets per second, perhaps with short burts into the thousands, something that a single core can comfortably handle.

the8472
  • 40,999
  • 5
  • 70
  • 122
  • Well the class I'm using for sockets doesn't really support multithreading but I can worst case scenario use dlls. I guess you don't need multiple threads but I feel like implementation would be easier with that (for example executing get_peers while also receiving requests) – raz Feb 19 '23 at 11:29
  • 1
    A DHT can be easily implemented on a single thread by using non-blocking IO, an epoll()/select() loop to check read/write readiness and if there's something that needs a timeout (e.g. when waiting for responses) then polling with a timeout can provide ticks. I'm doing something like that [in my Rust DHT impl](https://github.com/the8472/bt-dht-rs/blob/cfd58cad97306449120f1aa693b9c3547dda1fe0/src/main.rs#L80-L101). Using threads is possible, but generally overkill. Actually, even a blocking IO API should be fine as long as you can set a read timeout. – the8472 Feb 19 '23 at 14:34
  • That's awesome thanks. Do you know if such tools exists in c#? – raz Feb 19 '23 at 15:33
  • 1
    Not a C# expert, but the Socket class has `Blocking` and `Poll` properties, so I guess that's supported. – the8472 Feb 19 '23 at 16:36
  • Actually I still have one question left, how would you handle ping requests in just one thread and loop? Do you save the node and bucket every time you need to ping? – raz Feb 20 '23 at 04:28
  • I guess you can make due with generators – raz Feb 20 '23 at 04:47
  • in my implementation I keep track of outgoing requests, including pings, because I associate some state with them. The bucket can be found by the node ID of the responding node. that has nothing to do with threads or not, just with overall state associated with the dht. – the8472 Feb 20 '23 at 13:04
  • I'm dumb this makes a lot of sense you can just go to the appropriate bucket in the routing table based on the id – raz Feb 20 '23 at 13:35