I'm not sure of the labelling "//Server" in your question, but I'm assuming the following code is the server code:
InputStream in = client.getInputStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
int i = 0;
while((i = in.read()) >= 0) {
bOut.write(i);
}
String complete = new String(bOut.toByteArray(), "UTF-8");
This will continue to read, blocking each time, until it gets a value from read()
less than zero. That only happens if the stream is closed.
It really looks like you need to establish your own protocol. So instead of looking for "<=0" look for some constant value that signals the end of the message.
Here's a quick demonstration of what I mean (I didn't have time yesterday). I have 3 classes, Message
,MyClient
(which also is the main
class), and MyServer
. Notice there isn't anything about sending or receiving a newline. Nothing is setting tcpNoDelay. But it works fine. Some other notes:
- This code only sends and receives a single request and response.
- It doesn't support sending multiple
Message
instances. That would require checking for the start of a Message
as well as the end.
Message
class:
public class Message {
public static final String MSG_START = "<message>";
public static final String MSG_END = "</message>";
private final String content;
public Message(String string){
content = string;
}
@Override
public String toString(){
return MSG_START + content + MSG_END;
}
}
MyServer
class
public class MyServer implements Runnable{
public static final int PORT = 55555;
@Override
public void run(){
try {
ServerSocket serverSocket = new ServerSocket(PORT);
Socket socket = serverSocket.accept();
String message = getMessage(socket);
System.out.println("Server got the message: " + message);
sendResponse(socket);
}catch (IOException e){
throw new IllegalStateException(e);
}
}
private void sendResponse(Socket socket) throws IOException{
Message message = new Message("Ack");
System.out.println("Server now sending a response to the client: " + message);
OutputStream out = socket.getOutputStream();
out.write(message.toString().getBytes("UTF-8"));
}
private String getMessage(Socket socket) throws IOException{
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
StringBuilder sb = new StringBuilder(100);
byte[] bytes = new byte[1024<<8];
while(sb.lastIndexOf(Message.MSG_END) == -1){
int bytesRead = in.read(bytes);
sb.append(new String(bytes,0,bytesRead,"UTF-8"));
}
return sb.toString();
}
}
MyClient
class
public class MyClient {
public static void main(String[] args){
MyClient client = new MyClient();
Thread server = new Thread(new MyServer());
server.start();
client.performCall();
}
public void performCall(){
try {
Socket socket = new Socket("127.0.0.1",MyServer.PORT);
sendMessage(socket, "Why hello there!");
System.out.println("Client got a response from the server: " + getResponse(socket));
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
public String getResponse(Socket socket) throws IOException{
String response;
StringBuilder sb = new StringBuilder(100);
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
while(sb.lastIndexOf(Message.MSG_END) == -1){
int bytesRead = in.read(bytes);
sb.append(new String(bytes,0,bytesRead,"UTF-8"));
}
response = sb.toString();
return response;
}
public void sendMessage(Socket socket, String message) throws IOException{
Message msg = new Message(message);
System.out.println("Client now sending message to server: " + msg);
OutputStream out = socket.getOutputStream();
out.write(msg.toString().getBytes("UTF-8"));
}
}
The output
Client now sending message to server: Why hello there!
Server got the message: Why hello there!
Server now sending a response to the client: Ack
Client got a response from the server: Ack
Process finished with exit code 0
OutputStream
has.flush()
. Also, the way your write your JSON is broken: it uses the JRE's default encoding. Why don't you use a JSON library instead? – CordialityOutputStream
doesn't flush at all.flush()
does nothing, whenever you call it. The problem is that you are reading until EOS but the sender is never closing the stream. – Illyricum