So i have two threads, one is server socket, second is clinet. Server reads some message from the client using readAllBytes()
and then send this message back using write()
and then flush()
. Client basically does the same thing but in reverse order. Here is the code:
package org.example;
import java.io.*;
import java.net.*;
public class Main {
public static void main(String[] args) {
new Thread(() -> {
try (ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream()) {
System.out.println("SERVER: reading message...");
byte[] bytes = in.readAllBytes();
System.out.println("SERVER: message from the client: " + new String(bytes));
System.out.println("SERVER: sending message back...");
out.write(bytes);
out.flush();
System.out.println("SERVER: message sent back.");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try (Socket socket = new Socket("localhost", 8080);
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream()) {
System.out.println("CLIENT: sending message...");
out.write("hello world".getBytes());
out.flush();
System.out.println("CLIENT: message sent.");
System.out.println("CLIENT: reading response from the server...");
byte[] bytes = in.readAllBytes();
System.out.println("CLIENT: response from the server: " + new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
However here is the output:
SERVER: reading message...
CLIENT: sending message...
CLIENT: message sent.
CLIENT: reading response from the server...
Although client says that he sent message, server gives no response and i don't know why. And if I make it so that the server only reads the the message from the client and does not send anything back, and i make client only sending the message and nothing read back:
new Thread(() -> {
try (ServerSocket serverSocket = new ServerSocket(8080); Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream()) {
System.out.println("SERVER: reading message...");
byte[] bytes = in.readAllBytes();
System.out.println("SERVER: message from the client: " + new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try (Socket socket = new Socket("localhost", 8080); OutputStream out = socket.getOutputStream()) {
System.out.println("CLIENT: sending message...");
out.write("hello world".getBytes());
out.flush();
System.out.println("CLIENT: message sent");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
Everything will work just fine:
SERVER: reading message...
CLIENT: sending message...
CLIENT: message sent.
SERVER: message from the client: hello world
readAllBytes
reads all the bytes. How does the server know that "hello world" is the entirety of the data that the client is going to send? It doesn't, so it waits for more. readAllBytes
will read everything until the stream is closed. But if you close the stream, you will also close the socket, which means the client will not be able to read the response from the server.
So you need to establish some way to indicate "this is the end of the message", so that the server can stop reading the message, and start sending the response. This could be a specific byte, or a specific sequence of bytes. Alternatively, the server can be made to only read a fixed amount of bytes each time, by using readNBytes
.
Since you are sending text, I would suggest that you wrap the input/output streams with something that actually understands text, instead of working with the raw bytes. For example, you could use a Scanner
to read, and a PrintStream
to write. Then it is very convenient to use a line separator as "the end of the message" (println
and nextLine
).
try (ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();
Scanner in = new Scanner(socket.getInputStream());
PrintStream out = new PrintStream(socket.getOutputStream())) {
System.out.println("SERVER: reading message...");
String s = in.nextLine();
System.out.println("SERVER: message from the client: " + s);
System.out.println("SERVER: sending message back...");
out.println(s);
out.flush();
System.out.println("SERVER: message sent back.");
} catch (Exception e) {
e.printStackTrace();
}
try (Socket socket = new Socket("localhost", 8080);
PrintStream out = new PrintStream(socket.getOutputStream());
Scanner in = new Scanner(socket.getInputStream())) {
System.out.println("CLIENT: sending message...");
out.println("hello world");
out.flush();
System.out.println("CLIENT: message sent.");
System.out.println("CLIENT: reading response from the server...");
String s = in.nextLine();
System.out.println("CLIENT: response from the server: " + s);
} catch (Exception e) {
e.printStackTrace();
}