Quick question regarding this
Socket(String host, int port)
If I use these arguments in a client, how would a specify the server have a name and thus reference it in the client?
EDIT
Please excuse me if it's vague.
I'm writing and instant messenger in java and using this constructor for the client side socket, it wants to receive the host's name as a string and the host's port as a int. What I'm asking is how do I set/find the host's name in this case?
For example, is the String simply "127.0.0.1" if I'm running it locally? Or is it a specified name like "JavaServer" that I set somewhere somehow?
Well, you could read the documentation for that constructor :-)
It's either a host name (e.g. "chatserver.domain.com") or and IP address as a String (e.g. "192.168.1.10")
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 want to let the user have the freedom to choose a specific local address to connect to the target server since there might be customized routing policies, but want the program to pick up an ephemeral port instead of specifying one since that may need manual-test of local port availability.
I checked the constructors of "Socket" and "InetSocketAddress", it seems none of them have one to do the above task (even though it can pick up a local address and an ephemeral port simultaneously), and there is no method to do so after the initialization.
There is a construtor
public Socket(InetAddress address,
int port,
InetAddress localAddr,
int localPort)
throws IOException
that should be suitable for your requirement. If localPort is 0, the system will pick a free port.
You can create a Socket and call connect on it later.
Socket socket = new Socket(); // no idea where to connect
socket.connect(addressAndPort); // now I know.
What I do is have a TCPRegistry for testing purposes. This component takes care of aliased ports. e.g. host.port1. It gives it an ephemeral port on the server and allows the client to connect to it using the same string.
Note: to allow the client to start before the server I can ask it to pre-build these ServerSocket in the unit test.
Finally, at the end of the test, I can either check all Sockets and ServerSockets were closed, or forcefully clean them up.
It is designed for NIO, but could be adapted for plain IO TCPRegistry
why do we have to create an object of InetSocketAddress?
but for ServerSocket we just use int to enter port number
Example:
try(
ServerSocketChannel listener = ServerSocketChannel.open();
ServerSocket serverSocket = listener.socket()
){
serverSocket.bind(new InetSocketAddress(2266));
//we can't use serverSocket.bind(2266);
}catch (IOException e){
e.printStackTrace();
}
Your question is somewhat unclear.
ServerSocket#bind() establishes the local end of the connection. If your system has more than one network adapter and/or more than one IP address, AND you wanted to connect the socket using a specific local adapter or IP address, then you would provide a complete InetSocketAddress(host,port) with both host and port, where the host part was one of your local IP addresses.
In the default case where you have only one IP address, or have more than one but don't care which one is used as the source, you can omit the host and just specify the port, as in your example.
The API is defined this way. A TCP connection is symmetrical, and is defined by its two endpoints. An endpoint is a pair (host,port). This applies to BOTH ends of the connection. Thus the bind() call takes an InetSocketAddress parameter. For convenience, InetSocketAddress will assume the default host that specifies "use any available interface" if you provide only a port.
The API designers could have added a bind(int port) method to build the InetSocketAddress(port) behind the scenes, but clearly didn't feel it was necessary.
InetSocketAddress creates a socket address where the IP address is the wildcard address and the port number a specified value
wildcard is special IP address which can be used for binding. If you don't want to listen "everything" but maybe spesific IPs, say, 5.5.5.5 for example, you will be binded to that IP address but not others.
But without the IP part to it means any IP will be listened so pretty much no difference for this particular usage.
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.
I've tried many examples on web and one of them is this:
http://zerioh.tripod.com/ressources/sockets.html
All of the server-client socket examples work fine when they are tested with 127.0.0.1
BUT it never ever EVAR works on two different computers with actual raw real IP address ("could not connect to host" on telnet and "connection timed out" when tested on java client - the server program just waits for connection)
Note:
Firewall is turned off for sure
IP address from ipconfig didn't work
IP address from myipaddress.com (which is totally different for no reason than that from ipconfig) didn't work
What is it that I'm missing?
If I can only figure this out...
Try binding on 0.0.0.0. This tells your socket to accept connections on every IP your local can accept upon.
Based on the comment where the the following snippet of code is mentioned:
requestSocket = new Socket("10.0.0.5", 2004); // ip from ipconfig
it would be better to use the hostname instead of the IP address in the constructor, as the two-parameter Socket constructor with a String argument expects the hostname as the String, and not an IP address. A lookup of the IP address is then performed on the provided hostname.
If you need to pass in an IP address, use the two-parameter constructor that accepts the InetAddress as an argument. You can then provide a raw IP address to the InetAddress.getByAddress method, as shown in the following snippet:
InetAddress addr = InetAddress.getByAddress(new byte[]{10,0,0,5});
You'll need to be careful when specifying arguments via the byte array, as bytes are signed in Java (-127 through +128), and numbers beyond this range (but valid octets of IP addresses) may have to be specified using Integer.byteValue.
Finally, it should be noted that it is important to specify the IP address of the remote machine, as visible to the client. The IP address listed at myipaddress.com may be the address of a proxy, as that is the public IP of your entire network as visible to the host server at myipaddress.com. Therefore, you ought to be specify the IP address of the remote machine that is visible to your machine and not myipaddress.com.