I have two servers that need to be able to send requests to each other, and I need them to be able to communicate over a NAT or router. One server has a registered domain, and it is always waiting for connections. The other server sends the first request (the login request) to the first server when it starts. What is the best way to allow the two server to continue to communicate?
Huh? This shouldn't be a problem. If the first server, the one with the registered name, is always contacted by the other one.
As long as the second machine has general Internet connectivity, all it needs to do is e.g. open a TCP/IP connection to firstserver.example.com or whatever, and they should be able to continue to communicate over that connection indefinitely.
This is no different from general surfing using NAT.
Related
I understand why a server would need sockets for incoming data, but I do not understand why it is necessary that a socket connecting to another computer needs a source port.
While others have mentioned the exact reason why, let me illustrate the point by giving you an example:
Say you want to ssh to your server. OK, you ssh in and do some stuff. Then you tail a log file. So now you don't have access to the console anymore. No problem you think, I'll ssh again...
With one port number, if you ssh again that second connection will be a mirror of the first since the server won't know that there are two connections (no source port number to tell the difference) so you're out of luck.
With two port numbers you can ssh a second time to get a second console.
Say you browse a website, say Stackoverflow. You're reading a question but you think you've seen it before. You open a new tab in your browser to stackoverflow to do a search.
With only one port number the server have no way of knowing which packet belongs to which socket on the client so opening a second page will not be possible (or worse, both pages receive mixed data from each other).
With two port numbers the server will see two different connections from the client and send the correct data to the correct tab.
So you need two port numbers for client to tell what data is coming from what server and for the server to tell what data is coming from which socket from the client.
A TCP connection is defined in terms of the source and destination IP addresses and port numbers.
Otherwise for example you could never distinguish between two connections to the same server from the same client host.
Check out this link:
http://compnetworking.about.com/od/basiccomputerarchitecture/g/computer-ports.htm
Ultimately, they allow different applications and services to share the same networking resources. For example, your browser probably uses port 80, but your email application may use port 25.
TCP communication is two-way. A segment being sent from the server, even if it is in response to a segment from the client, is an incoming segment as seen from the client. If a client opens multiple connections to the same port on the server (such as when you load multiple StackOverflow pages at once), both the server and the client need to be able to tell the TCP segments from the different connections apart; this is done by looking at the combination of source port and destination port.
The challenge: We have a number of clients in distributed outposts that I have to manage with a central server. As some clients are located in DMZ or behind proxies, they should be connecting to the server!
As I only have to deal with one client at a time, the server doesn't necessarily have to be able to handle multiple clients simultaniously, however, I would like to see a list of the clients that are trying to connect to the server. Plus, I would like to see more information about the clients than just the IP address, for example the geographic location and some information, if the client has some files in a specific directory that the central server is interested in. My question is, how I best do smth like that.
Sure, I could simply show every client trying to connect in a listbox and accept only the one that I want to connect with, but is that really the way to go? I doubt I can get more information about the client than it's IP address?
I was wondering, if this calls for UDP. The clients send UDP datagrams that just inform the server that they are alive and that they want to connect. On the server, I see all these clients listed with the data they sent. I can then select one client, send an answer/"connection request" with UDP so that this particular client will connect via TCP to the server?
Is that possible?
This sounds like using a hammer to crack a nut. Just have them all connect via TCP. Then you get their presence, their IP address, anything else they care to send you. Deal with them all at once. It's not hard.
I am building an app that uses a async socket connection with a web server.
For sending large amounts of data I would like to connect two iPhones into a Peer to Peer connection using an async socket. I am more familiar with GCDAsyncSocket than to the iOS SDK socket API.
I have done something similar, but only within a local network were I would user NSNetService to publish a presence and get the addresses needed from the p2p connection.
Can you give me a hint on how to connect two iPhone over the internet using a p2p socket connection?
I do not know much about NSNetService but it seems that it only works in a local network. If you want to establish a p2p connection from an iphone to another you will always have the problem of several NATs (Network address translators) in your route. How to find the address and route to the peer? And how to get trough all the firewalls and NATs?
I am working on an app that needs to deal with the same problem and I have answered a similar question before which I will cite here:
Actually, it IS possible. You may want to google for something called
"UDP hole punching" or "TCP hole punching".
The main approach in short: Assuming you got something like a relay
server, that is some server in the internet that is publicly
addressable from every private LAN that is connected to the www. No
you have your two clients A and B in (different) private LANs, with
some Network address translation (NAT) going on, that want to
establish a peer to peer connection.
First of all both will tell the server their IP address and the port
they have in their own LAN. In the UDP or TCP packet, the server will
find the public address and port of the device (or the NAT (router)).
So the server knows the private and the public IP address as well as
the ports.
If now A wants to communicate with B, it asks the server for help. The
server will send a message to B that A wants to communicate with her
telling her A's public and private IP and port. A gets back B's public
and private information and port.
Now here is where the magic happens. Both clients now send packets out
to establish a connection simultaneously to the private and public
addresses of the other party and thus punching a whole in their NATs
such that incoming connections will not be blocked. Even if one
party's connection establishing packets will arrive before this whole
is created, the other's packets will get through to such that a
connection can be created.
Beware of some NATs that scan the data for IP addresses and translate
them as well, but if you encrypt your data or change the appearance of
the address (complement, ...) you will be fine.
Now the master question, how can the server communicate with one of
the clients without an active connection. Well in this case you can
use "connection reversal" and apple's "push notifications". Use the
"push notifications" (pn) to tell a client behind a NAT that there is
something of interest going on and that it should contact the server.
Once it has done that the connection is active and can be used in the
previous described fashion.
I hope this helps some people that get to this problem although the
post is quite old!
Now if you find this solution helpful and you try to implement it, please tell me if you are successful in getting the public ip and port of the server-client connection on the server side. You can also answer my question about this on stackoverflow.
Please be specific, u may use GCDAsyncSocket to connect 2 phones, u may use sample code from Github.
I've noticed that if you want to write an application that utilizes listening sockets, you need to create port forwarding rules on your router. If I want to connect two computers without either one of the the computers messing about with router settings, is there a way that I can get the two clients to connect to each other without either of them using listening sockets? There would need to be another server somewhere else telling them to connect but is it possible?
Some clarifications, and an answer:
Routers don't care about, or handle ports, that is the role of a firewall, which do port forwarding. The router/firewall combined device most of us have at home adds to the common misunderstanding.
Can you connect two computers without ServerSocket? No. You can use UDP (a stateless, connectionless communication protocol), but the role of a ServerSocket is to "listen" for incoming connection requests, and generate a Socket from those requests, which creates a communications channel between two endpoints. A Socket has both an InputStream and an OutputStream, so it can both read at write at either end. At that point (once the connection is made), the distinction between client/server is arbitrary, since a Socket is a two-way connection object, which allows both sides to send/receive.
What about proxying? Doesn't that allow connections between two computers without a ServerSocket? Well, no, because the server that's doing the proxying still has to be using a ServerSocket. Depending on what application you're trying to implement, this might be the way to go, or or might just add overhead. Even if there were "another server somewhere else telling them to connect", somebody has to listen for a connection request, which is the job of the ServerSocket.
If connections are happening over already open ports (most publicly accessible servers have ports <1024 not blocked by firewalls, but exceptions exist), then you shouldn't need to change firewall settings to get the connection to work.
So, to reiterate, the ONLY role of a ServerSocket (as far as your question is concerned) is to listen for incoming connection requests, and from those requests, create a Socket, which is a two-way communications channel between the two end points.
To answer the question, "How do I design a peer-to-peer app that avoids using listening sockets?", you don't. In the case of something like Vuze, the software acts as both client and server simultaneously, hence the term "peer", vs. "client" or "server" alone. In Vuze every client is a server, and every server (except for the tracker) is a client.
If you need a TCP connection between the 2 computers and both of them are behind routers (and you don't want to set up port forwarding) I think the only other possibility you have is having a third server somewhere that isn't behind a firewall running a ServerSocket and accepting connections between your 2 other computers and proxying communications between the 2. You can't establish a TCP Connection between the 2 without one listening to a socket and the other connecting to it.
Q: If I want to connect two computers without either one of the the
computers messing about with router settings, is there a way that I
can get the two clients to connect to each other
Yes: have the server listen on an open port :)
I apologize for the weird question wording... here's the design problem:
I am developing a server (on Linux using C++, FWIW) that provides a service to many instances of a client application running on consumer PCs.
I want the following:
1) All clients first identify themselves to a "gatekeeper" server application. Consider this a login procedure, with credentials like a user name and password being passed in. Call the gatekeeper program "gserver". (for gatekeeper.)
2) Once each client has been validated, it is then placed into a long term connection with one of several instances of a different server application running on the same physical server box bound to the same server address. Call any of these instances "wserver" (for "working" server.)
So, what the client sees is that a "gatekeeper" application gives it passworded access to one of several "working" servers running on the same box.
Here is the "real" challenge: we want to exclusively use a "well known" port number for the inbound server connections (like port 80 or 443, say.) Or, our own "well known" port.
We would prefer not to have to make the client talk to a second port on the server for the long term connection phase with wserver(n). The problem with this, of course, is that only one server process at a time can be bound to the same port and server address.
This implies that a connection made by the client with gserver must also fill the role of the long term connection. The only way I see to accomplish this is that gserver must, after login, act like a proxy and copy traffic between itself and the client to the particular wserver(n) that the client is bound to logically.
It would be ideal if a TCP/IP connection first made between client(n) and gserver could be somehow "transported" to another application on the same server, intact, and could then be sustained by one of the wserver(n) instances for the long term connection.
I know that web servers do something like this for spreading out server loads. "Load balancing". The main difference here is that the "balancing" is the allocation of a particular user to a particular wserver(n) instance. But I also have the impression that load balancing is a kind of proxying - which I am trying to avoid (since it complicates the architecture and adds overhead as well as a single point of failure.)
This is a conceptual and design question. Don't worry about source code examples, unless they are absolutely essential to get the ideas across. If we pin down an approach, I can code it up.
Thanks!
What you are looking for is file descriptor passing. See UNP 15.7. One well-known heavy user of this facility is postfix.
I developed such an application long time ago. Since multiple servers can't listen on the same port. What you need is to have gserver listening on the well-known port. Once connection is established, pass the connection to the other servers via an Unix socket. Once the connection is passed to other server, gserver is out of picture. It can die and the other server will be still serving the connection.
I dont' know if this applies to your design, but the usual solution (as implemmented by the xinetd daemon) is to fork() and then exec() the process. For example, xinetd may serve services like rlogin, rsh, tftp, telnet, etc. which are actually served by different programs. This will not be useful to you if your wservers are processes already running in the system.