I want to write a peer to peer network application and have the following problem.
Two nodes in the network, A and B are trying to establish a connection to each other at the same time. When they both accept the connection of the other, there will be two TCP sockets opened.
Only one socket should be used for the communication between the two, because it is enough to communicate in both directions. What is an elegant solution to this problem?
Thanks!
You should not be trying to establish two simultaneous connections at the same time. That is a flaw in your p2p design. The two peers need to coordinate with each other (such as by exchanging messages via a central server that they are both connected to and knows who they both are). A decision needs to be made first about who is listening and who is connecting. One peer only opens a listening socket and that info gets sent to the other peer so it knows where to connect. If that conection fails (ie, the listening peer is behind a NAT/firewall), the peers need to be notified and a decision made to swap roles. The previously-connecting peer now opens a listening socket and that info gets sent to the previously-listening peer so it knows where to connect. If that connection fails (ie, the now-listening peer is also behind a NAT/firewall), then a direct connection between the two peers is not possible without additional help (NAT hole punching, for instance). In some situations, a direct connection is simply not possible, so data being exchanged between them would have to be proxied through the central server.
Related
I am trying to setup peer to peer networking and am trying to understand how this works.
Normally in Client to Server connection, I will connect to the server IP and port. Behind the scenes, it will create a client socket bound to a local port at the local ip, and the packet is sent to the router. The router will then NAT the local port and the local socket, to the client public ip and a different public client socket with a destination for the server IP and port.
When the server responds, the router then DENATs the public client ip and public client port back to the local ip and local port, and the packet arrives at the computer.
In a Peer to Peer networking, I may have the peer's public IP, but it is shared by many machines and the router hasn't allowed a connection yet, so there isn't a open port I can send the data to.
There was then an option that both peers contact a server. That opens a port on the router. Then the peers send packets to each other's client port.
However, usually the router will only accept packets from the same IP the request was made to, so the two peers cannot reuse the server's connection.
How do the two peers talk to each other in this scenario ?
Peer-to-peer networking works exactly the same way as client/server networking. Only one of the peers will become a server and the other a client.
Normally in a peer-to-peer app like bittorrent all peers are also servers but of course for any individual connection one machine must take the role of the client. However a single peer may have multiple connections. So for any single peer some of the connections to it will be server sockets and some will be client sockets.
How this works with NAT is exactly the same as a client/server architecture. You must configure your router to NAT back to your peer application in order for others to connect to it. If not then your peer can only connect to other peers but other peers cannot connect to you. For example, if your bittorrent client is generally acting slow, not managing to get a lot of connections and not managing to finish downloading some torrents this often signifies that you have not configured your router's port forwarding back to your PC for your bittorrent client.
For the use-case of non-expert users (consumers) there are several ways to get around NAT automatically without requiring your users to configure their routers. The most widely used method is UPnP (Universal Plug and Play). However a lot of more expert users who can configure their own routers often disable UPnP because it is a fairly well known DDoS target. So if you do decide to use UPnP you should make it optional for more advanced users to disable it if they don't want to use it.
For cases where you need a guaranteed connection regardless of router configuration then your app cannot be 100% peer-to-peer. You'd need a relay server that acts as a server to both peers that will forward the packet form the sending client peer to the receiving client peer. Of course, the disadvantage of this is that you now have a fixed cost of maintaining a server to support your app just like traditional client/server systems but in this case you're using peer-to-peer to reduce server costs, not eliminate the server.
One example of this "hybrid" approach is cryptocurrencies like Bitcoin and Ethereum. They need a core group of servers to exist in order to work. However, for these protocols the servers run the same software as the clients - they're all just nodes. The only difference is that you don't shut down the servers whereas most people quit their bitcoin wallet once they've done using it (unless they're mining). Another example that is similar is the TOR network. There is a set of core TOR nodes that act as the "server" part of the network ensuring that the network always exist.
You said it yourself: "peers send packets to each other's client port". Therefore, the router will "accept packets from the same IP the request was made to".
Say, Alice is behind router A and Bob is behind router B.
Having learned their public endpoints from a server, Alice will send UDP packets to Bob's public IP, and Bob will send UDP packets to Alice's.
Having seen Alice talk to Bob's IP, router A will accept UDP packets from Bob.
Having seen Bob talk to Alice, router B will accept UDP packets from her as well.
That is, some initial packets might be rejected as coming from the blue, but after both parties have initiated communication on their side, routers will have no reason to block what follows.
In terms of Symmetric NAT Traversal using STUN 2003, by sending a packet to Bob, Alice is creating a door for Bob in A. On the other side, by sending a packet to Alice, Bob is creating a door for Alice in B.
The trick in UDP hole punching seems to be for the routers to reuse the same NAT tunnel for different IPs - so that the port discovered by a server is the same as the port reused for direct communication.
We can talk with different IPs from a normal UDP socket (by skipping connect and using sendto), so it's kind of logical that a tunneled socket would be able to do the same.
BitTorrent peers connect with each other via TCP (mainly). When a peer A tries to connect to peer B, does peer B also needs to try to connect with A simultaneously so the TCP 3-way handshake happens and they form a connection? If not, why?
Also, I have been studying three bittorrent client implementations. While they start TCP connections with the obtained peers, I noticed none of them opens a TCP socket to listen on the port they are announcing to the tracker. Does it mean no one can initiate connection to them? Shouldn't they create such TCP socket?
When a peer A tries to connect to peer B, does peer B also needs to try to connect with A simultaneously so the TCP 3-way handshake happens and they form a connection? If not, why?
Connection setup is a general TCP feature, not specific to bittorrent. One side initiates the connection by calling connect on an unconnected socket and the other side has a listening socket configured on which it calls accept in a loop to create create connection-specific sockets for each accepted incoming connection.
There is a simultaneous open flow for connection setup but that's rarely relevant and the connect/accept flow is used by bittorrent clients.
I noticed none of them opens a TCP socket to listen on the port they are announcing to the tracker.
They generally do and should unless process privileges are insufficient to bind a particular port or another process is already listening on it, in which case they should log a warning at least.
If you used a portscan then you may be seeing firewall or NATs getting in the way rather than the client not having a listening socket open. Instead you could use something like netstat (may need some additional arguments, depending on OS) to show listening sockets.
If they truly do not have a listening socket open then yes, that would be a problem since they could not accept incoming connections and only talk to a more limited set of clients (those that do).
Bittorrent being a peer-to-peer protocol means that clients should be equals (peers) which means they should be equally capable of initiating and accepting connections.
I'am just started to studying bittorent protocol and have one question about bittorrent clients that uses same ports for all incoming connections.
Here is example of my problem:
1st connection: A local peer listening on 1.0.0.1:1 and receives connection from remote peer with address 2.0.0.2:2. OK. Start PWP
2nd connection: A local peer listening on 1.0.0.1:1 and receives connection from remote peer with address 3.0.0.3:2. OK. Start PWP
3rd connection: A local peer listening on 1.0.0.1:1 and receives connection from remote peer with address 2.0.0.2:2 but with another InfoHash. ???
Is 3rd connection possible or remote peer(2.0.0.2:2) have to track it's connections to local peer(1.0.0.1:1) and will connect to local peer through different port and also announce himself 2nd time to tracker with different port or/and peer id?
Yes, it is possible for two peers to use more than one connection, sharing torrents with different InfoHashes at the same time. There are two different cases depending on what type of transport protocol the connection is done over.
TCP connection
When a bittorrent peer shares over TCP, it opens up a incoming port that is announced to the tracker(s) and that port is the one used to connect to by every other peer that initiates a connection to that peer. However, a peer that initiates and makes a outgoing connections uses a different port number for every outgoing connection.
That makes it possible to uniquely identify every connection by its (IP:PORT<->IP:PORT)-pair.
uTP/UDP connection
When a peer shares over uTP/UDP it uses the same port for both incoming and outgoing connections. To make it possible to differentiate between the connections, the uTP protocol extension instead uses a connection_id that is unique for every connection.
The advantage with using the same port for both incoming and outgoing connections is that it makes UDP hole punching possible.
The peer makes a separate announce to the tracker(s) for every different InfoHash.
All modern clients reuses the same incoming port for all torrents it shares.
I never figured this one out and I've been programming for years. How do P2P programs like chat programs or torrent programs manage to create connections between two peers without peers opening any ports? I know I haven't opened up a port for Skype yet I can send and receive large files to and from my friends, and I'm pretty sure all those gigabytes don't go through Skype servers. Or do they?
What about torrenting? I can upload data to peers and I haven't opened any ports either.
I'm pretty sure the answer will be language-nonspecific, but in case I'm wrong, I code mostly in C++. Thanks in advance.
You only need to "open a port" for inbound connections. One peer will open a listening port, then instruct the other peer to connect to it. If the connection fails, the peers will usually swap roles and try again. If the connection still fails, then either the transfer is aborted, or a server relay is used if feisable.
For each listening peer, if the port is behind a router/firewall, the peer can either programmably instruct the router/firewall to open a port for forwarding inbound connections to the peer (some routers support uPNP for that, and some firewalls have their own API), or the peer can try using various "hole punching" techniques to trick the router/firewall into opening a forwarding port (some routers/firewalls are not susceptible to this).
Read this for more details: How Skype & Co. get round firewalls
I am in the process of developing a peer to peer app,
I am a bit confused by the following scenario:
Lets say my application will use an outgoing port 1863 - which is also used for msn messenger(if this is not the port lets assume it is)
Now, client executes my app and connects to my server at port 1863.
I am a bit confused if this is going to produce any problems.
I know that 2 apps can use same port for outgoing communication. But what happens to the data coming back?
Also, does my client need to open port for my app to run correctly??
I know that 2 apps can use same port for outgoing communication. But
what happens to the data coming back?
That's exactly the problem the source port solves. The peer can always differentiate between 2 connections based on it. When it sends replies, what was the source port now becomes the destination port allowing the original receiver to correctly pass data to the rightful processes.