views:

79

answers:

3

I try to play with sockets a bit. For that I wrote very simple "client" and "server" applications.

Client:

import java.net.*;

public class client {
    public static void main(String[] args) throws Exception {
    InetAddress localhost = InetAddress.getLocalHost();
    System.out.println("before");

    Socket clientSideSocket = null;
    try {
        clientSideSocket = new Socket(localhost,12345,localhost,54321);
    } catch (ConnectException e) {
        System.out.println("Connection Refused");
    }
    System.out.println("after");

    if (clientSideSocket != null) {
        clientSideSocket.close();
    }
    }
}

Server:

import java.net.*;

public class server {
    public static void main(String[] args) throws Exception {
    ServerSocket listener = new ServerSocket(12345);

    while (true) {
        Socket serverSideSocket = listener.accept();
        System.out.println("A client-request is accepted.");
    }

    }
}

And I found a behavior that I cannot explain:

  1. I start a server, than I start a client. Connection is successfully established (client stops running and server is running). Then I close the server and start it again in a second. After that I start a client and it writes "Connection Refused". It seems to me that the server "remember" the old connection and does not want to open the second connection twice. But I do not understand how it is possible. Because I killed the previous server and started a new one!

  2. I do not start the server immediately after the previous one was killed (I wait like 20 seconds). In this case the server "forget" the socket from the previous server and accepts the request from the client.

  3. I start the server and then I start the client. Connection is established (server writes: "A client-request is accepted"). Then I wait a minute and start the client again. And server (which was running the whole time) accept the request again! Why? The server should not accept the request from the same client-IP and client-port but it does!

A: 

It is likely the operating system has not yet shutdown the sockets, try the netstat command (should work on Windows or Unix/Linux). If you run it immediately after you close client or server you should still the socket in "TIME_WAIT" "CLOSE_WAIT" or something similar. You wont be able to reuse those ports until they are fully closed.

M. Jessup
A: 

Per Question #3: Many clients can connect to a server attached to a single port. Apache runs on port 80 but that doesn't mean only one person can view your website at a time. Also you are closing your client socket before you're opening a new one.

Jeremy
Jer, I know that many clients can connect to the server throw the same server-port. But clients should be connected from different client-IP and/or different client-ports. The server cannot accept a second connection from the same client-IP and client-port. Yes, in my case I close the socket on the client-side, but the server keeps this socket opened. So, according to my understanding, the server should not allow to open a new socket with the client IP-port pare which is already occupied.
Roman
You keep the java Socket open. The OS will have received the info that the connection is closed, mark its internal handle your java socket refer to as closed, and will happily accept a new connection from the same source port, binding that socket to a new Java socket when you accept it. Your existing non-closed Java socket will simply not refer to any open sockets anymore.
nos
@nos, I keep the Socket open from one side (server side) and it is closed from the client side. Do you say that server will, somehow, notice that the client closed its side of socket and, as a consequence, the server will close his side of socket and will accept a new request from the client located on the old IP and old port?
Roman
Yes. Sockets are a feature of the OS, the TCP stack of the OS manages the connections and the sockets. You just have a handle to a socket the OS manages. When the client closes the connection, TCP requires it to send a FIN packet, and the OS will receive and handle those(and close the socket).
nos
+3  A: 
  1. When you close the server , the OS will keep the socket alive for a while so it can tell the client the connection has been closed. This involves timeouts and retransmissions which can take some time. You might find some info here and here. If you want your server to be able to immediately rebind the same socket, call setReuseAddress(true) on it, though it might be the client sockets that's in a TIME_WAIT state.

  2. The socket is no longer in TIME_WAIT state, and can be reused again by any program.

  3. Your client code just connects, closes the socket and then exits. As far as the server/OS tcp stack is concerned, these are different connections - it's fine to reuse the source port as long as any prior connection have been torn down. (Note that the OS might not tear down all of the housekeeping of the connection immediately after you call .close() or your program exits, there's some time delay involved so it can be sure all packets have been sent/received)

nos