Duckman Duckman - 21 days ago 9
Java Question

Java TCP - Client Server help needed

Hi and thanks in advance.

I am currently trying to create a client server program where the server responds to the client based on different requests coming in from the client.

Here is what I am trying to do for the first of the requests (the issue is the same for all of the clients different requests to the server, so fixing just this would help me fix all of them):

1) The client connects to the server

2) The client sends logon information to the server

3) The server checks the logon information for validity

4) The server sends a response saying that login was successful.

5) Client receives and displays response.

Here is the Client (the first try block is located in the client frame, the second within an action listener for a button on the client frame):

try
{
mySocket = new Socket("localhost", 2016);
}
catch (UnknownHostException e1)
{
e1.printStackTrace();
}
catch (IOException e1)
{
e1.printStackTrace();
}

try
{
DOS = new DataOutputStream(mySocket.getOutputStream());
DOS.writeUTF(txtName.getText() + " " + txtPassword.getText());
DOS.flush();
DOS.close();

DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());
JOptionPane.showMessageDialog(null, DISLog.readLine());
}
catch(IOException e1)
{
e1.printStackTrace();
}


Server:

System.out.println("Waiting for client....");
ServerSocket myServerSocket = new ServerSocket(2016);
Socket mySocket = myServerSocket.accept();

myClientHandler = new EZFILEHandler(mySocket);

//Log in check

DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());

StringTokenizer ST = new StringTokenizer(DISLog.readLine());
String Name = ST.nextToken();
String Password = ST.nextToken();

//DISLog.close();

boolean Found = myClientHandler.matchUser(Name,Password);

DataOutputStream DOS = new DataOutputStream(mySocket.getOutputStream());

if (Found == true)
{
DOS.writeUTF("You are logged in.");
DOS.flush();
LoggedIn = true;
}

if (Found == false)
{
DOS.writeUTF("You could not log in.");
DOS.flush();
}


Here is the code for the ClientHandler mentioned in the Server code:

public EZFILEHandler(Socket newConnectionToClient)
{
try
{
mySocket = new Socket("localhost", 2016);
}
catch(Exception e)
{
e.printStackTrace();
}
}


Running the above code will give a
Socket is closed
exception at this line in the client:
DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());
, so I then tried commenting out the line:
DOS.close();
in the client to keep the socket open, but that causes the button which calls the client code to freeze the program and points to this line if I terminate the program:
JOptionPane.showMessageDialog(null, DISLog.readLine());
.

So my question is this: How do I allow the client and server to respond to each other in different ways without the socket closing or the jswing freezing from not being allowed to finish processing?

Also, how would it be possible for me to allow multiple clients to logon to the server and all their requests still be processed safely?

Thank you.

Answer Source

If you are writing a Swing program, your socket communication should be on its own SwingWorker thread.

Let's ignore that, and pretend it is just debugging code, not intended to stay.

DISLog.readLine() will read until it reaches the newline character, or the end of the input stream. The server is executing (say) the following:

DOS.writeUTF("You are logged in.");
DOS.flush();

No newline there. And flush() does not close the stream; it simply ensures all the characters are sent, not left in the buffer to be combine with the next set of characters to send.

Catch-22? Yup! The client is waiting for \n, and the server is waiting for more commands from the client.

Change the client to use readUTF().

Update Looks like you need to change the server to use readUTF() as well. The server is probably not getting past the new StringTokenizer(DISLog.readLine()) call unless the client closes the socket.