Hi,
I'm making a TCP Server/Client chat program. I have two clients. The problem I'm having is that I can send one message from one of the clients, but then consecutive messages from the same client get sent to the server, but the server doesn't pass them on until I send a message from the other client.
Like this:
Client1: Hi! (works)
Client1: Hello (nothing)
Client2: Hello! (works, and Client1's second message appears)
It's sort of like the server isn't flushing it's PrintWriter until client2 sends a message?
I'm explicitly flushing the PrintWriter both server- and client-side.
Here's my server code:
public void startServer(){
this.stop = false;
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(PORT);
System.out.println("Server started at " + InetAddress.getLocalHost() + ":" + PORT);
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
while(!stop){
try {
Socket socket = serverSocket.accept();
System.out.println("Connection made with " + socket.getInetAddress());
EchoConnection conn = new EchoConnection(socket);
Thread thread = new Thread(conn);
thread.start();
} catch (SocketTimeoutException e){
} catch (IOException ex) {
stop = true;
}
}
try {
serverSocket.close();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
private class EchoConnection implements Runnable {
private Socket socket;
private Gson gson;
PrintWriter printWriter;
BufferedReader bufferedReader;
public EchoConnection(Socket socket){
this.socket = socket;
this.gson = new Gson();
}
@Override
public void run() {
try {
printWriter = new PrintWriter(socket.getOutputStream(), true);
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String encodedMessage;
do {
encodedMessage = bufferedReader.readLine();
System.out.println("Received Message! Processing...");
if(encodedMessage.contains("userInfo:")){
String[] parts = encodedMessage.substring(encodedMessage.indexOf(":") + 1, encodedMessage.length()).split(",");
String username = parts[0];
int udpPort = Integer.parseInt(parts[1]);
createClient(username, udpPort, socket);
}else if(encodedMessage.contains("DISCONNECT:DONE")){
System.out.println("Closing connection with " + socket.getInetAddress());
removeClientFromList(socket);
} else {
String messageType = getMessageType(encodedMessage);
if(messageType.equals("private")){
String newMessage = formatEncodedMessage(encodedMessage);
PrivateMessage privateMessage = gson.fromJson(newMessage, PrivateMessage.class);
String userTo = privateMessage.getTo();
String userFrom = privateMessage.getFrom();
String messageToSend = privateMessage.getMessage();
sendPrivateMessage(userTo, userFrom + ": " + messageToSend);
} else if(messageType.equals("broadcast")){
String newMessage = formatEncodedMessage(encodedMessage);
BroadcastMessage broadcastMessage = gson.fromJson(newMessage, BroadcastMessage.class);
sendBroadcastMessage(broadcastMessage.getMessage());
} else if(messageType.equals("disconnect")){
String newMessage = formatEncodedMessage(encodedMessage);
DisconnectMessage disconnectMessage = gson.fromJson(newMessage, DisconnectMessage.class);
sendDisconnectMessage(disconnectMessage.getMessage());
}
}
} while(encodedMessage != null && !encodedMessage.equals("((STOP))"));
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if(printWriter != null){
printWriter.close();
}
if(bufferedReader != null){
bufferedReader.close();
}
if(socket != null){
socket.close();
}
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Here's the client code:
private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {
if(btnConnect.getText().equals("Connect to Server")){
String username = JOptionPane.showInputDialog("Enter your username:");
this.username = username;
lblConnectionStatus.setText("Status: Connecting to server...");
try {
socket = new Socket(HOST_NAME, HOST_PORT);
} catch (IOException ex) {
Logger.getLogger(ClientUI.class.getName()).log(Level.SEVERE, null, ex);
}
new Thread(new Runnable(){
@Override
public void run() {
try {
datagramSocket = new DatagramSocket();
int udpPort = datagramSocket.getLocalPort();
printWriter = new PrintWriter(socket.getOutputStream(), true);
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
printWriter.println("userInfo:" + username + "," + udpPort);
printWriter.flush();
receive();
String response;
do {
response = bufferedReader.readLine();
txtAreaChat.append(response + "\n");
} while(!stop);
} catch (IOException ex) {
Logger.getLogger(ClientUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}).start();
lblConnectionStatus.setText("Status: Connected!");
btnConnect.setText("Disconnect");
} else if(btnConnect.getText().equals("Disconnect")){
printWriter.println("DISCONNECT:DONE");
printWriter.flush();
stop = true;
try {
if(printWriter != null){
printWriter.close();
}
if(bufferedReader != null){
bufferedReader.close();
}
if(socket != null){
socket.close();
}
lblConnectionStatus.setText("Status: Disconnected");
btnConnect.setText("Connect to Server");
listConnected.setListData(new String[0]);
} catch (IOException ex) {
Logger.getLogger(ClientUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void txtMessageKeyPressed(java.awt.event.KeyEvent evt) {
if(evt.getKeyCode() == KeyEvent.VK_ENTER){
String text = txtMessage.getText().trim();
if(text.startsWith("@")){
int beginIndex = text.indexOf("@") + 1;
int endIndex = text.indexOf(" ");
String toUser = text.substring(beginIndex, endIndex);
boolean foundUser = false;
for(String onlineUser : currentlyConnected){
if(onlineUser.equals(toUser)){
foundUser = true;
break;
}
}
if(foundUser){
beginIndex = text.indexOf(" ") + 1;
endIndex = text.length();
String message = text.substring(beginIndex, endIndex);
PrivateMessage privateMessage = new PrivateMessage(message, username, toUser);
String json = privateMessage.toJSON();
printWriter.println(json);
printWriter.flush();
} else {
JOptionPane.showMessageDialog(this, "Could not find user " + toUser + "!");
}
} else {
BroadcastMessage broadcastMessage = new BroadcastMessage(text);
String json = broadcastMessage.toJSON();
printWriter.println(json);
printWriter.flush();
}
}
}
What I have tried:
I have tried flushing the PrintWriter both server- and client-side. I am also running each client connection in it's own Thread as shown above.