I am trying to make a simple client/server application using Socket, BufferedReader and BufferedWriter. Authorization works good, and when i am sending first message everything also works, but when i am trying to send second message i catch the exception:
Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: java.net.SocketException: Канал обірвано
at utils.SocketManager.writeMsg(SocketManager.java:33)
at client.Chat.sendMessage(Chat.java:53)
at client.Chat.lambda$new$0(Chat.java:37)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2314)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:407)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6620)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
at java.desktop/java.awt.Component.processEvent(Component.java:6385)
at java.desktop/java.awt.Container.processEvent(Container.java:2266)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4995)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:98)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Caused by: java.net.SocketException: Канал обірвано
at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:413)
at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:433)
at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:812)
at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1120)
at java.base/sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:313)
at java.base/sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:409)
at java.base/sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:414)
at java.base/sun.nio.cs.StreamEncoder.lockedFlush(StreamEncoder.java:218)
at java.base/sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:205)
at java.base/java.io.OutputStreamWriter.flush(OutputStreamWriter.java:263)
at java.base/java.io.BufferedWriter.implFlush(BufferedWriter.java:372)
at java.base/java.io.BufferedWriter.flush(BufferedWriter.java:359)
at utils.SocketManager.writeMsg(SocketManager.java:31)
... 37 more
Here is piece of server code:
private static void handleClient(Socket socket){
try (BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream()));
BufferedReader reader = new BufferedReader(
new InputStreamReader(
socket.getInputStream()))) {
String command = "";
while(!command.equals("Exit")) {//here starts endless loop
if (reader.ready()) {
command = reader.readLine();
switch (command) {
case "LogIn" -> logIn(writer, reader);
case "SendMsg" -> sendMsg(reader);
case "Exit" -> {
clients.remove(socket);
socket.close();
}
}
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static void sendMsg(BufferedReader reader) throws IOException{
String message = reader.readLine();
for(Socket client : clients) {
try(BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(
client.getOutputStream()))) {
writer.write(message);
writer.newLine();
writer.flush();
}
}
}
Client:
public Chat(String login) {
this.login = login;
Thread thread = new Thread(new ReceiveMessage());
thread.start();
sendButton.addActionListener(e -> sendMessage());
}
public void openFrame() {
frame = new JFrame("YurChat");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setContentPane(mainPanel);
Toolkit toolkit = Toolkit.getDefaultToolkit();
frame.setBounds(toolkit.getScreenSize().width / 2 - 325, toolkit.getScreenSize().height / 2 - 200, 550, 300);
}
private void sendMessage() {
SocketManager.writeMsg("SendMsg");//server does not get command second time
String message = login + ":\t" + messageTextField.getText();
SocketManager.writeMsg(message);//throws exception
messageTextField.setText("");
}
private class ReceiveMessage implements Runnable {
@Override
public void run() {
while(true) {
if(SocketManager.isReaderReady()) {
String msg = SocketManager.readMsg();
chatTextArea.append(msg);
}
}
}
}
}
SocketManager:
public final class SocketManager {
private static final Socket socket;
private static final BufferedWriter writer;
private static final BufferedReader reader;
static {
try {
socket = new Socket(
PropertiesUtil.getProperty("socket.ip"),
Integer.parseInt(PropertiesUtil.getProperty("socket.port")));
writer = new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream()));
reader = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void writeMsg(String message) {
try {
writer.write(message);
writer.newLine();
writer.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String readMsg() {
try {
return reader.readLine();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static boolean isReaderReady() {
try {
return reader.ready();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void close() {
try {
writer.close();
reader.close();
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Full code is here: https://github.com/lucifer116664/ClientServerChat.git
I debugged this app and found that when i am sending message second time client is sending command "SendMsg", but server does not get it and stops in the endless loop waiting for command.
Thanks in advice.
Thanks to Mark Rotteveel i got the answer. I just modified sendMsg method by putting try with resources into if(client != socket) (sending message everyone besides client who wrote it) and everything works great.
private static void sendMsg(Socket socket, BufferedReader reader) throws IOException{
String message = reader.readLine();
for(Socket client : clients) {
if(client != socket) {
try (BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(
client.getOutputStream()))) {
writer.write(message);
writer.newLine();
writer.flush();
}
}
}
}