I wonder how to connect two clients over the internet without opening ports on the server side. If this is impossible, how does e.g. Skype establish a connection between the talking people? (Speech goes directly to the clients)
Is there a way to use a "master server" where both clients connect to and then getting a direct connection together?
Thanks for every answer.
Skype uses the concept of Supernodes, that relay communications on behalf of two clients. The Skype user directory is decentralized and distributed among the supernodes in the network.
The Supernodes try to make both ends to negotiate directly the connection, but if it's not possible due to firewalls, NAT, etc they relay the traffic on behalf of two or more clients.
Related
I am trying to make a two-way instant messaging app over two different networks. One of these networks is mine, which has port forwarding enabled(sends traffic on certain port to specific ip address). My problem is that I need a two way connection(sockets can only send to serverSockets, serverSockets can't send to sockets). Is there a way to connect to a computer via a pre-existing connection? Is there a library for this? ie. socket.connect(serverSocket.getConnection, 5001); (I have made my own classes which handle all the Input/Output Streams and sockets, I just need a library for a function I can put in the class).
If what you're asking for is to have a computer exposed to the internet to directly connect to a computer behind a NAT, you might get your app working if you are able to implement something similar to reverse ssh tunneling. See here and here, for a java library.
But I would recommend some sort of client-server approach for this, in which everyone connects to the server, and through the server they connect to each other.
I have java programs for my client and server, and they work fine within the same wifi network. But I need the clients to be able to connect to the server from the open internet. In questions like these
How to connect client and server with the help of ip address which are connected to internet through different wifi?
https://coderanch.com/t/667020/java/Socket-connections-networks
the solution is to manually reroute a port to the server from the router, making it open to connections from the outside. Is there a way to do this with just software on the server? I don't understand why manually dedicating ports is necessary since of course other applications on my computer (like games) that I install communicate with their servers back and forth without me having to manually go in and flip switches.
How can I achieve this with just software running on my server?
If there isn't another way, how do other applications communicate openly without manual router changes, and will opening up ports through my router result in security issues?
You would need to change the architecture of your application. Currently, your server is behind a firewall which blocks connections from the internet - you want this! If you allowed all traffic from the internet to connect indiscriminately to your server, it would be very vulnerable to attack.
Other applications install and communicate without port-forwarding because the developer provides a server on the internet to act as a proxy between clients. The client connects out to the internet which is generally not blocked on home networks. Internal connections going out are considered less harmful than connections coming in.
I'm currently working on a messaging program in java, and I planned on using UDP to send messages from the user to a central server, and I planned on using possibly TCP for messages from the server going back to the user. My main question is, how can I achieve this without requiring the client to port forward?
P2P clients like skype use subtle tricks to connect peers behind firewalls. The different techniques used are outlined here:
http://www.h-online.com/security/features/How-Skype-Co-get-round-firewalls-747197.html
Very simply, the client has to establish the TCP connection to the server, even if the primary (indeed if not only) data flow is in the opposite direction.
Programs like skype either use a common port that is open (port 80) or put a rule in the firewall to allow another port to communicate. Additionally a program can open ports above 1024 without adminisrative permissions although depending on the type of connection it may need to set up UPnP or keep an active channel to a server open.
I want to be able to connect (java)clients to each other without opening ports in their router or forwarding on their local network. I want to mimic the behavior of webtrc but in java, using a server for signaling. The server will have to receive session keys from both clients that wants to connect to each other, sending the first clients key to the second client and vice versa. After the signaling, the both clients can connect to each other using this key, and the packets will find their way through the router without opening ports and forwarding.
The goal is to make a framework out of this to be able to write applications that don't require a server with huge bandwidth that can read from one client and write to the other, for every pair of clients that wants to send data to each other. What I'm asking for is simply guidelines for this could be implemented.
TLDR: I want to be able to directly connect two clients, in two completely different networks, with the help of a public server and without any router configuration for the clients.
This technique is called Hole punching
"Hole punching is a computer networking technique for establishing communications between two parties in separate organizations who are both behind restrictive firewalls. Used for applications such as online gaming, P2P and VoIP, both clients establish a connection with an unrestricted third-party server that uncovers external and internal address information for them. Since each client initiated the request to the server, the server knows their IP addresses and port numbers assigned for that session, which it shares one to the other." from wikipedia
also take a look on this answer
I am trying to create a java chat application for my networking class. As of right now I am stuck trying to connect to someone behind a different router. The way I have my project right now is I have a client program and a server program. The client programs first logs into the server program which logs their IP and port in a database and then the server gives them back the list of their friends with their IPs and ports. Then the client closes down the connection to the server and tries to connect to another client using the information the server sent back. So far my program only works connecting to the server and getting the friends IP and port but when I use those values to connect to the other client I cant connect.
socket = new Socket();
socket.setReuseAddress(true);
socket.setKeepAlive(true);
socket.setSoLinger(true, 10);
socket.bind(new InetSocketAddress(Port));
socket.connect(new InetSocketAddress(host, SERVER_PORT));
reusePort = socket.getLocalPort();
Above is a snippet of java code used to connect to the server then below is what i do on the client side.
ss = new ServerSocket(reusePort);
So now technically I am listening on the same port I used to connect to the server with which is logged in and is retrievable to another client and is in the NAT table with my ip and port. I am not sure what I am missing or if there is some protocol or something that I have to do. I have looked at TCP and UDP hole punching but I am not sure how that is actually accomplished or how to implement it.
Any suggestions would be appreciated.
If you want to send a message you'll need to set up port forwarding on any device that acts as a server (any device which creates a socket server). Port forwarding is done on the Router. The reason you cannot connect to the other client is because they are hidden behind their routers firewall. Their address to the rest of the world is actually the address of the router, not of their physical computer. On their local network they have a different address then what the rest of the world sees, and the router figures out what messages from the outside world need to be sent to the client based on an address translation table.
Given your architecture, this would mean that all clients need to have their routers doing port forwarding, which is of course unfeasible (imagine gtalk or aim requiring users to do port forwarding).
The more common architecture is to have the Server do the work of rebroadcasting messages to the connected clients and maintain tables to lookup whose talking with who. This way there is a single server which will need a static ip (or be port forwarded), and all users are simply clients which connect to the server socket and read messages from it.
For actual code describing the second architecture please see http://pirate.shu.edu/~wachsmut/Teaching/CSAS2214/Virtual/Lectures/chat-client-server.html. Then the machine which is running the server code either needs a static ip or if it is behind a router needs traffic from the port it is listening on to be forwarded.
So on the server code you will bind to the ip assigned from your router (something like 192.168.1.2 at some port say 5000). Then go to your routers configuration page (it may be 192.168.1.1 see http://www.wikihow.com/Port-Forward/Open-Ports-on-a-Linksys-Router), and forward port 5000 to the address 192.168.1.2.
The Interactive Connectivity Establishment (ICE) protocol combines various NAT traversal utilities such as the STUN and TURN protocols in order to offer a powerful mechanism that allows Offer/Answer based protocols such as SIP and XMPP to traverse NATs.
This project provides a Java implementation of the ICE protocol that would be usable by both SIP and XMPP applications. The project also provides features such as socket sharing and support for Pseudo TCP.
ice4j is maintained by the Jitsi community.
ice4j