9

I'm developing a game for a class that I am in, and it is about 99% done. However, I realized there is a problem: If the server and client disconnect, and the client attempts to reconnect (and the server is back up and running fine), the client is not making a new connection.

The server and client are both multi-threaded. If I send the client a Kick message, what happens is the client will close its socket. If I reconnect, I get a SocketException: socket closed even though whenever connect is pressed, a new Client is constructed, which is basically just a class that creates a socket and connects to the server with a get/send thread.

Do you think there is anything I am doing illogically? It is like it is attempting to use the old Socket and Client that were constructed, but if I do some println calls, I can see that it does construct a new one and they are in different memory locations.

Thanks!

Alberto Solano
  • 7,972
  • 3
  • 38
  • 61
user1089097
  • 155
  • 1
  • 1
  • 7
  • Check this question --> http://stackoverflow.com/questions/2456607/can-i-close-and-reopen-a-socket – Alberto Solano Dec 11 '11 at 16:16
  • 1
    That didn't seem to help. I have realized that the new client is connecting because if I connect with a different name, the new name is realized on data sent. I forgot to mention that, for whatever reason, data is received fine. It's whenever I try to write to the outputstream when I get a socketclosed exception. – user1089097 Dec 11 '11 at 16:26

2 Answers2

13

After closing a socket, you cannot reuse it to share other data between Server and Client classes. From the Java Socket API, about close() method's description:

Any thread currently blocked in an I/O operation upon this socket will throw a SocketException.

Once a socket has been closed, it is not available for further networking use (i.e. can't be reconnected or rebound). A new socket needs to be created.

Closing this socket will also close the socket's InputStream and OutputStream.

If this socket has an associated channel then the channel is closed as well.

Then, it isn't possible to close a socket and reopen it. That's the reason, I think, of the exception being thrown.

Alberto Solano
  • 7,972
  • 3
  • 38
  • 61
  • Thanks for your input. I am constructing a new Socket, and the weirdest thing is that after I construct the new one, if I write something to it's outputstream immediately after connecting, it writes it and I receive a response correctly. But if I call writeObject later, it gives the error! – user1089097 Dec 11 '11 at 16:30
  • @user1089097 Excuse me, I added my question after seeing your comment. It's really a strange problem. Maybe you close the Server socket before you write in the outputstream. Can you post some code in your question? – Alberto Solano Dec 11 '11 at 16:37
  • I have sorta figured out what the problem is. The chatbox is sending to the wrong client -- nothing is wrong in the client or server. I'm not sure how to fix that, because I construct the view with the client...but at least I know why. Thanks. – user1089097 Dec 11 '11 at 16:48
  • @user1089097 You are welcome. Now I'm glad you know why the problem is happening. If I understood well, you are developing a simple chat application. Some time ago, I written a simple program like yours and the socket managing is not easiest, but, with commitment, it's possible to solve the problems. If you are doubtful, you can ask here. ;-) – Alberto Solano Dec 11 '11 at 16:57
  • Now I'm even more confused. When The GUI is constructed, it is sent the Client. If I print out the clients name in the constructor, it is the new client's name. If I print it out in the command listener, it is the old clients name! This is why I can receive, but not send. I have no idea what could cause this, though! – user1089097 Dec 11 '11 at 17:16
  • 1
    I understood that the program still recognizes the new client as the old client disconnected before. But if I can't see some code, I will be more confused than you and I cannot help you properly! – Alberto Solano Dec 11 '11 at 17:23
  • I changed the markers of the Client to be Static and Volatile and now all is good. Thanks for being someone to bounce ideas off of. – user1089097 Dec 11 '11 at 17:26
  • Thanks, no problem. :-) I'm glad you solved and your application is working as expected. – Alberto Solano Dec 11 '11 at 17:47
4

It can be easy! I made this program (server side):

import java.net.ServerSocket;
import java.net.Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;

public class Host{
    public static void main(String[] args) throws Exception{
        while(true){
            ServerSocket ss = new ServerSocket(1300);
            Socket s = ss.accept();
            DataInputStream din = new DataInputStream(s.getInputStream());
            String msgin = din.readUTF();
            System.out.println(msgin);
            ss.close();
            s.close();
            din.close();
        }
    }
}

Client side:

import java.net.Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;

public class Client{
    public static void main(String[] args) throws Exception{
        while(true){
            Socket s = new Socket("localhost", 1300);
            DataOutputStream dout = new DataOutputStream(s.getOutputStream());
            dout.writeUTF("hello");
            s.close();
            dout.close();
        }
    }
}

It works, beacuse you can declare tons of Sockets with the same ServerSocket, so for example this works too:

ServerSocket ss = new ServerSocket(1300);
Socket a = ss.accept();
Socket b = ss.accept();
Socket c = ss.accept();

and you have 3 Sockets... Remember: java waits for a client to connect when you declare a Socket! Code:

Client:

import java.net.Socket;

public class client {
    public static void main(String[] args) throws Exception{
        Socket a = new Socket("localhost", 1300);
        Thread.sleep(3000);
        Socket b = new Socket("localhost", 1300);
        Thread.sleep(3000);
        Socket c = new Socket("localhost", 1300);
        Thread.sleep(3000);
        a.close();
        b.close();
        c.close();
    }
}

Server:

import java.net.ServerSocket;
import java.net.Socket;

public class server {
    public static void main(String[] args) throws Exception{
        ServerSocket ss = new ServerSocket(1300);
        System.err.println("Listening...");
        Socket a = ss.accept();
        System.err.println("1");
        Socket b = ss.accept();
        System.err.println("2");
        Socket c = ss.accept();
        System.err.println("3");
    }
}
mfekete101
  • 45
  • 2
  • 6