[JAVA] серверная / клиентская программа с несколькими клиентами. Клиенты блокируют друг друга на стороне сервера.
Привет,
Я делаю программу чата TCP-сервер / клиент. У меня два клиента. Проблема, с которой я сталкиваюсь, заключается в том, что я могу отправить одно сообщение от одного из клиентов, но затем последовательные сообщения от одного и того же клиента отправляются на сервер, но сервер не передает их, пока я не отправлю сообщение от другого клиента.
Подобный этому:
Клиент1: Привет! (работает)
Клиент1: здравствуйте (ничего)
Клиент2: Здравствуйте! (работает, и появляется второе сообщение Client1)
Это похоже на то, что сервер не сбрасывает свой PrintWriter до тех пор, пока client2 не отправит сообщение? Я явно очищаю PrintWriter как на стороне сервера, так и на стороне клиента.
Вот мой серверный код:
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); // TODO: Implement proper disconnect message stating which Client disconnected 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); } } }
Вот клиентский код:
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 the pressed key is the 'Enter' key if(evt.getKeyCode() == KeyEvent.VK_ENTER){ // Create MessageSender object // Trim the whitespace from the text in the message box String text = txtMessage.getText().trim(); // Check if there is an '@' tag at the beggining of the message to indicate a private message if(text.startsWith("@")){ // Get the username int beginIndex = text.indexOf("@") + 1; int endIndex = text.indexOf(" "); String toUser = text.substring(beginIndex, endIndex); boolean foundUser = false; // Check if user is currently online for(String onlineUser : currentlyConnected){ if(onlineUser.equals(toUser)){ foundUser = true; break; } } // If the user is currently online, create a private message object with the message and username 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 notify the user that the user they are trting to send a private message to could not be found (not online/doesn't exist) } else { JOptionPane.showMessageDialog(this, "Could not find user " + toUser + "!"); } // Else, create a broadcast message with the text in the message box } else { BroadcastMessage broadcastMessage = new BroadcastMessage(text); String json = broadcastMessage.toJSON(); printWriter.println(json); printWriter.flush(); } } }
Что я уже пробовал:
Я пробовал промывать PrintWriter как на стороне сервера, так и на стороне клиента. Я также запускаю каждое клиентское соединение в своем собственном потоке, как показано выше.