This question seems like something very obvious to ask, and yet I spent more than an hour trying to find an answer.
First I host and wait for someone to connect. Then, from another instance of the application, I try to connect with a socket - for the constructor, I use InetAddress, port. The port is always right, and everything works if I use "localhost" for the address. However, if I type my IP (the one I got from Googling "what is my ip"), I get an IOException. I even sent the application to someone else, gave him my IP, and it didn't work.
The aim of the application is to connect two computers. It's in Java. Here is the relevant code.
Server:
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
Client:
InetAddress a = InetAddress.getByName(ip);
Socket s = new Socket(a, port);
I don't get past that. Obviously, the values of int port and String ip are taken from text fields.
Edit: the purpose of my application is to connect two non-local computers.
As mentionned by Greg Hewgill, if you are behind a NAT Device (Router, etc...) you will have to do some Port Forwarding.
Basically, your public IP Address that you get from using "What is my IP" from google is your public IP Address, but since you are using a router with multiple computers connected to it, there is a protocol that maps multiple computers to a single public address called NAT.
What you'll need to do is tell your router to forward the incoming packets on a certain port to a certain computer.
The way to do this is highlighted in this article http://www.wikihow.com/Port-Forward
Related
When we send data (in this case) to a client/server, does this really matter to use the same port number?
My guess is no, because it doesn't matter which port you are using when sending data to. (The protocol gives it to you randomly internally - this is the idea?) The only thing has to be kept, the port has to be any availabe one on the receiver machine(above 1000, because those are reserverd by the system), and if that receiver decides to send something back, he or she will have enough information about sender: his IP address, port number ect. As far as i know, a received packed provides with all of that info.
Below is just an illustration of what i've said above.
public class Server {
public static void main(String[] args) {
GameServer server = new GameSever(9822);
server.start();
InetAddress address = null;
int port = 7877;
try {
address = InetAddress.getByName("192.168.0.2");
} catch (UnknownHostException e) {
e.printStackTrace();
}
server.send(new byte[] { 1, 2, 3 }, address, port);
}
}
When a server listens on a computer, it specifies a port it wants it's connections coming in from , so ports are important for setting up servers. This is useful as you can have multiple applications listening on different ports without the different applications accidentally talking to eachother. So you should decide on a port that isn't a standard( 80 is for HTTP for example) to exclusively use for you gameserver so the client knows which port to send the requests to.
If you want to handle multiple connections at once the best thing to do is threading.
When we send data (in this case) to a client/server, does this really
matter to use the same port number? My guess is no, because it doesn't
matter which port you are using when sending data to.
Firstly, use the terms client and server distinguishly(as generally client initiates by sending the message, to which the server responds).
Next, the port which you're using is logically of no significance, the reason being server uses request.getPort() to determine the port while seding the response; (request is a DatagramPacket sent by the client).
Though you can hardcode the port at server(if known beforehand), but, it is a bad idea. What in those applications where you've no idea about who sent the datagram packet?
Java documentation by Oracle also uses an example of client-server where client's port number is left for the constructor to pick. It mentions :
Mostly, the client uses a constructor that does not require a port number. This constructor just binds the DatagramSocket to any available local port.
It doesn't matter what port the client is bound to because the DatagramPackets contain the addressing information. The server gets the port number from the DatagramPackets and send its response to that port.
MORE INFO (taken from Java Network Programming) :
public DatagramSocket() throws SocketException
This constructor creates a socket that is bound to an anonymous port. For example:
DatagramSocket client = new DatagramSocket();
Pick this constructor for a client that initiates a conversation with a server. In this scenario, you don’t care what port the socket is bound to because the server will send its response to the port from which the datagram originated. Letting the system assign a port means that you don’t have to worry about finding an unused port. If, for some reason, you need to know the local port, you can find out with the getLocalPort() method.
NOTE : The same socket can receive the datagrams that a server sends back to it(underlying implementation).
Whereas, the below constructor creates a socket that listens for incoming datagrams on a particular port, specified by the port argument :
public DatagramSocket(int port) throws SocketException
Use this constructor to write a server that listens on a well-known port.
Short answer:
Your guess is correct.
Longer answer:
Client gets a random port number when sending data to a server and each packet has a header which contains the info about client's port, ip address ect. So server can easily retreive this information and send anything back.
Whereas the server needs to be bind to a specific port in order to clients be able to send data to that server because when you use UDP, you need to specify an IP address and a port.
I have a serversocket running on a port say 7761 in my server with ip say 10.2.110.43
now there are many client that run on different servers waiting for connection on port 7761, and write data in ascii format to that port.
I want the serversocket to verify the client-ipadress and then accept connection from client.
Is there a way to do that?
If you don't mind running under a SecurityManager and the list of IP addresses is static, you can accomplish this via the security.policy file. Just grant SocketPermission"accept" to only those IP addresses you want to accept connections from. However doing it in code or the firewall as suggested in another answers is probably preferable.
We see in the following code, we can't check address of counterparts before accept() but after:
Socket client = serverSocket.accept()
if( acceptedClients.contains( client.getInetAddress()) {
...
}
else {
client.close();
}
With acceptedClients a collection of well known InetAddress.
If you don't want the connection to reach your Java ServerSocket#accept() unless it comes from a specific IP, you will have to configure your firewall to do this.
You can always validate the IP address after the connection is established and immediately close it if it's not from the right IP.
My ServerSocket listens to LAN Connections and accepts them well, but when I try to connect to the same through my Phone - using the 3G connection - it doesn't seem to connect.
I tried using getMyIP site to get the IP and try to connect to it, it does get the right IP (checked with my router) but then no connections are accepted at all.
I tried opening the port on windows 7 and on my router altogether.
I put those lines in my Server constructor:
ss = new ServerSocket(port);
host=ss.getInetAddress().getHostAddress();
and I get the ip on host to 0.0.0.0
Thanks for your help.
- While you are at LAN, you can use the Private IP as well as Public IP ranges
- But when you are using the Internet to access the Server which is at your place, then you need to have a static Public IP address.
- You can ask for a static Public IP address from your ISP at some extra cost, there are also some site over net that some how provides a static IP on the basis of your Dynamic IP.
Private IP ranges Can't be used over the Internet.
Class A - 10.0.0.0 - 10.255.255.255
Class B - 172.16.0.0 - 172.31.255.255
Class C - 192.168.0.0 - 192.168.255.255
You need to have a public IP address. If you have a router it must pass traffic for the port you want to expose to the internet to your machine. If you have a firewall, it must allow external connections to this port.
All the changes you do are the same regardless of language you use and there is nothing you can do from Java to work around needing to do these things.
Check your firewall if it allows incoming connection. You need to make and exception there.
you need to bind explicitly the IP address on your machine which is allocated for that instance of time by your ISP.
You can get the IP address allocated to you by running ipconfig command on windows command prompt.
Use the following code to bind to a specific IP address
InetSocketAddress insa = new InetSocketAddress("22.23.23.111", 9090);
ServerSocket ss = new ServerSocket();
ss.bind(insa);
String host=ss.getInetAddress().getHostAddress();
System.out.println(host);
This prints the IP address allocated to you.
I am going through Sun's Java tutorial. I am in the lesson about sockets. There is the following code for a simple threaded server:
import java.net.*;
import java.io.*;
public class KKMultiServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(-1);
}
while (listening)
new KKMultiServerThread(serverSocket.accept()).start();
serverSocket.close();
}
}
The server is said to "keep listening for more incoming connections". I just don't understand how it's possible; the line serverSocket.accept() constructs a new (client) Socket object which is, according to the tutorial "bound to the same local port and has its...". Well, how is it possible that the server is communicating with the client and listening to more incoming connections on the same port? As far as I know, if a port is used for some connection it is blocked and cannot be used for more things.
So what am I getting wrong here?
Well, a socket is not one-to-one based on a port, it is unique on a tuple of (address, port). A connection - the pair of the local and remote sockets involved in the communication - is used to demux incoming data from a port to the correct socket, allowing multiple sockets on one port. See Wikipedia. In other words, the relationship of sockets to ports are N-to-1
getting multiple connections on the same port is entirely possible as each TCP connection is a (local host, local port, remote host, remote port) tuple as long as at least 1 is different the connections are distinct and won't interfere (besides bandwidth drops)
clients attempting to connect to a server generally get a port assigned from the OS that is not used currently
Listening sockets work like a receptionist in on a business's phone switch. Everyone calls the switch number, and the receptionist responds to each incoming call on the switch line by having someone else handle the call on another line. Even though the receptionist can only take one call at a time, the switch line is tied up only very briefly because it is used only to establish a connection.
[...]TCP demultiplexes incoming segments using all four values that comprise the local and foreign addresses: destination IP address, destination port number, source IP address, and source port number. TCP cannot determine which process gets an incoming segment by looking at the destination port only. Also, the only one of the [various] endpoints at [a given port number] that will receive incoming connection requests is the one in the listen state. (p255, TCP-IP Illustrated Volume 1, W. Richard Stevens)
The last sentence in the above quote is the key to understanding.
Interestingly, a socket isn't really identified by the combination of IP address and port. This is unique only in context, where the context is either a particular connection or the listening state. Only one listener socket can bind to a particular IP/port combination.
The short and sweet answer is that the port is blocked for OTHER programs and processes. Only the program that opened the port can now listen on it. BUT it can listen to many different clients on the same port.
When a client connects, it creates a unique socket. A socket is comprised of the listening IP address and port (the one you opened) AND the calling IP address and port. Because the caller's IP address and port are always unique, each socket is unique and identifiable to your listener.
Even if I connected to your program twice from the same machine, my machine would select a new and random source port for each connection -- thus ensuring that we have a unique socket each time.
Based on this link
The accept method waits until a client starts up and requests a connection on the host and port of this server (in this example, the server is running on the hypothetical machine taranis on port 4444). When a connection is requested and successfully established, the accept method returns a new Socket object which is bound to the same local port and has its remote address and remote port set to that of the client.The server can communicate with the client over this new Socket and continue to listen for client connection requests on the original ServerSocket This particular version of the program doesn't listen for more client connection requests.
Here is SO discussion which may clear confusion about how single port handles multiple client calls Port and Socket SO discussion .
To put it in simple terms, most of the webservers listen on port 8080 and multiple clients will access same port to access your website.
So I'm making a simple multiplayer online applet game, and I was testing it using multicast UDP sockets instead of the typical client-server connection. This is not meant to be efficient or safe for that matter, just an experiment. Only problem is, when I try to have other people join the game from their house, it won't connect them to me, but when I use two separate computers, one that's wired in and one that's on the wifi, it works seemlessly. They can join their own game and connect to their own network, but not other peoples. Am I missing something big here? I'll post the relevant code.
InetAddress group;
DatagramPacket packet;
DatagramPacket messagePacket;
MulticastSocket socket;
socket = new MulticastSocket(4446); //random port
group = InetAddress.getByName("228.5.6.7"); //multicast address
socket.joinGroup(group);
//typical code for sending a packet
packet = new DatagramPacket(messageBuf, messageBuf.length, group, 4446);
Any ideas? I'm rather new to networking but find it a fun challenge and would like to continue learning more about it..if you have any other tips on top of helping me to solve this problem it would be appreciated.
You probably figured this out by now, but yes there is a huge problem you are missing. It will always work if you are local because your router doesn't mind distributing packets behind the private LAN. Anything outside the network will not want to work because the client will try to send a packet to the server, but the server is behind a NAT(Network address translation) and since the router didn't see the server send out a packet first, the router will just discard the client's packet and never connect. However if the server sends out a udp packet to try to connect, the router likes to switch ports so you don't know which port the packet will come out of. That's what packet forwarding is for on the router. So when the client sends a packet, it goes to a different port than expected and the router still discards it. There are solutions such as "hole punching". The easiest solution tho is to have a dedicated server outside of any NAT to handle the requests.