简体   繁体   中英

How does Java ServerSocket get a new socket bound to the same local port after accept the client?

I am confused about Socket and ServerSocket port usages. Oracle's java tutorial about sockets says the following :

What Is a Socket?

Normally, a server runs on a specific computer and has a socket that is bound to a specific port number. The server just waits, listening to the socket for a client to make a connection request. On the client-side: The client knows the hostname of the machine on which the server is running and the port number on which the server is listening. To make a connection request, the client tries to rendezvous with the server on the server's machine and port. The client also needs to identify itself to the server so it binds to a local port number that it will use during this connection. This is usually assigned by the system.

If everything goes well, the server accepts the connection. Upon acceptance, the server gets a new socket bound to the same local port and also has its remote endpoint set to the address and port of the client. It needs a new socket so that it can continue to listen to the original socket for connection requests while tending to the needs of the connected client.

On the client side, if the connection is accepted, a socket is successfully created and the client can use the socket to communicate with the server. The client and server can now communicate by writing to or reading from their sockets.

I tried the following code to test. But it throws an exception.

try {
    ServerSocket serverSocket = new ServerSocket(8080);

    Socket socket = serverSocket.accept();

    // This prints 8080
    System.out.println("Local port of accepted socket : " + socket.getLocalPort());  

    // But this throws java.net.BindException: Address already in use: JVM_Bind 
    Socket myClientSocket = new Socket("www.google.com", 80, null, 8080);

} catch (Exception e) {
    e.printStackTrace();
}

My question is obvious. While the socket returned from serverSocket.accept() can use the same local port ( 8080 ) why the socket that I created cannot use it?

To keep it simple, the listening TCP socket is already explicitly bound to the port, so you can't explicitly bind a second TCP socket to the same port (unless both sockets are also explicitly bound to different IP addresses, not including INADDR_ANY).

The accepted sockets don't go through an explicit 'bind' process. They acquire their local IP address and port automagically, as does an outbound socket if you connect it without binding.

Your server and client are using the same local port to communicate. When you created the server socket you "said" it must listening on 8080 port. That´s ok. Any one that wants to communicate with your server socket must use such port.

But, right below you are creating a client socket that connects to google site using the port 80 (google is listening on that port) and, in the last argument, you are saying that this socket must use also the local port 8080 to establish the connection. Only one connection can use a port at a time, that´s why you are getting java.net.BindException, both server and client connections are using 8080.

My suggestion ... take the last two arguments from you socket client constructor, or change you local client port (always get a high number to avoid the same problem with other process):

Socket myClientSocket = new Socket("www.google.com", 80);

or

Socket myClientSocket = new Socket("www.google.com", 80, null, 58080);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM