BufferReader unexpected behavour - java

I'm trying to read data from socket using threading run method:
#Override
public void run() {
while(true){
try{
String o = "";
socketServer = new ServerSocket(port);
System.out.println("Waiting for connection on port "+port+".");
Socket socket = new Socket();
socket = socketServer.accept();
System.out.println("Connection got.");
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int c;
while(( c = input.read()) != -1)
o += (char)c;
PrintWriter output = new PrintWriter(socket.getOutputStream());
output.println("ok");
output.flush();
output.close();
input.close();
socket.close();
socketServer.close();
textFieldMessage.setText("Сообщение от "+socket.getInetAddress().getCanonicalHostName()+":\n"+o);
}catch(Exception e){
e.printStackTrace();
System.exit(-1);
}
}
}
But it's stucked on while loop. Debugger told that there was no -1 value at the end.
What's wrong here?

Because you're reading from a Socket, you'll never reach the end of the stream unless the socket or stream has been closed. So the while loop will block on input.read() because it won't return -1 until the client closes the stream/socket.
Not really sure what it is you are reading from the socket, but you could try using the BufferedReader's readLine() method. You can either know how many lines you need to read ahead of time, or end the reading with a blank line (like HTTP).

read() method of InputStream blocks until the data is available.
It can return -1 only when the end of the stream is detected.(Though it shouldn't be the case with sockets) So while loop will block if the data is not available i.e your read call will wait for the data to be read.
Note :
But if the value is -1, your program should have exited. So what are you reading ?

The peer isn't closing the socket, so you are never getting the -1, so you are blocking in the read() invocation after the last character received. Your strategy is flawed. You are reading to EOS and then expecting to be able to write a reply. Unless the peer shuts down his socket for output and then reads, this is never going to work. You need to define your application protocol properly. At present you are expecting the peer to do write/close/read. Doesn't make sense.

Related

Use writeUTF and readUTF for http requests in Java

This is a a Java method that tries to crawl a designated web page. I am using writeUTF and readUTF for socket communications to a server.
static void get_html(String host, String page, int port) throws IOException {
Socket sock = new Socket(host, port);
String msg = MessageFormat.format("GET {0} HTTP/1.1\r\nHost: {1}\r\n\r\n", page, host);
DataOutputStream outToServer = new DataOutputStream(sock.getOutputStream());
DataInputStream inFromServer = new DataInputStream(sock.getInputStream());
InputStream stream = new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8));
BufferedReader buf = new BufferedReader(new InputStreamReader(stream));
String outMsg;
while ((outMsg = buf.readLine()) != null) {
System.out.println("Sending message: " + outMsg);
outToServer.writeUTF(outMsg);
String inMsg;
try {
inMsg = inFromServer.readUTF();
} catch (EOFException eof) {
break;
}
System.out.println(inMsg);
}
sock.close();
}
The reason I am writing it this way was to mimic the c code, where you have a while loop of send() making all deliveries from a buffer, and another while loop of recv() from a buffer untill it hits 'null'. When execute my code, it just hangs there, I suspect that is due to a call of readUTF before I finished sending all my messages. If this is the case, is there any way to fix it?
You can't do this. HTTP is defined as text lines. writeUTF() does not write text, it writes a special format starting with a 16-bit binary length word. Similarly the HTTP server won't reply with that format into your readUTF() call. See the Javadoc.
You have to use binary streams and the write() method, with \r\n as the line terminator. Depending on the output format you may or may not be able to use readLine(). Best not, then you don't have to write two pieces of code: use binary streams again.
In fact you should throw it all away and use HttpURLConnection. Implementing HTTP is not as simple as may hastily be supposed.

Java - Server and Client not interacting (Socket)

I'm currently working on a small chat-program. The 2 classes, I have a problem with are the classes containing the clientside and the serverside of a socket. I want them to interact, sending a string from the server to the client, but the string isn't received apparently. I also don't get an error. Can someone explain, why this happens or how to fix it?
Codesnippet from the client:
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true) {
System.out.println("WAITING");
System.out.println(br.readLine());
}
} catch(Exception ex) { ex.printStackTrace(); }
Codesnippet from the server:
// Method of the code throws Exception
System.out.println("Waiting for someone to connect.");
Socket socket = serverSocket.accept();
System.out.println("Someone connected.");
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os, true);
while(true) {
System.out.println("WRITING");
pw.write("hi");
}
The output is currently:
server:
WRITING
WRITING
WRITING
WRITING
WRITING
...
client:
WAITING //only once
The client expects a complete line:
br.readLine()
and blocks until the line is complete.
But the server only sends "hi" repeatedly, without ever sending any EOL character:
pw.write("hi");
So the line never ends, and the client keeps blocking.
Use pw.println("hi");
The server buffer is not getting flushed. If you change pw.write(...) to pw.println(...) it should fix the issue - println(...) auto-flushes the buffer

Socket (C/Java) BufferedReader readLine() doesn't stop

I'm creating a forum with a Java interface and a C server.
I have trouble sending a message from C to Java....
I created a socket (named "socket") that works, like this :
socket = new Socket(adr, port);
//adr and port are defined before
But when doing this on the Java:
String str =null;
try {
BufferedReader br = new BufferedReader( new InputStreamReader(socket.getInputStream()) );
while ((str=br.readLine()) != null && str.length()>0)
{
System.out.println("str = " + str);
}
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
It just can't receive the message from the server.
It only shows the message when I brutally close the C server.
Here is how the server sends the message through the Socket :
write(client_sock,"0\0",strlen("0\0"));
I have no idea how to receive this "0" without closing the server. Any ideas ?
readLine() has read the send data, but blocks until a line feed or carriage return was read
If your client sees the data only if you are closing the server, than your server never sends a line feed or a carriage return.
Assuming, you want to send a file line by line to the client(example in java, it is my main language):
Socket client = server.accept();
OutputStream os = client.getOutputStream();
BufferedReader br = new BufferedReader( new InputStreamReader(Files.newInputStream(file.toPath())));
String str;
while ((str = br.readLine()) != null && str.length() > 0) {
os.write((str).getBytes());
}
br.close();
os.close();
As you can see, the server don't sends a line feed or carriage return. These were removed by readLine()!
So, the readLine() on your clientside is blocking until the socket will closed.
If you change the write instruction in that way:
os.write((str+"\n").getBytes());
your client is able to read the lines, even if the server is still writing the following lines.
You're looping until readLine() returns null or a blank line.
It returns null at end of stream. As you're reading from a socket, that only happens when the peer closes the connection.
It returns a blank line when the input contains a blank line.
Ergo the peer is neither closing the connection nor sending a blank line.

Java communication with TCP socket and PIC stuck in read()

I try to communicate with a java application to a µController in wifi (Flyport).
I have a problem with the java application :
It first create a socket to communicate with the Flyport server, then send a message and receive the Flyport answer.
Everything work fine until the read part. I'm polling the read() function of the BufferedReader until it return -1, but it doesn't. The first read works fine, all the answer are red, but the application stay stuck when it tries to read again.
My code is very simple :
Java application :
try (
Socket clientSocket = new Socket(hostName, portNumber);
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
)
{
...//Connection and sending message works fine
}
char[] buffer = new char[500];
while ((in.read(buffer)) != -1) { // first read() works fine, second read() stay stuck...
System.out.println(buffer); // display all answer sent by flyport
}
The code in the flyport :
while(isClientConnected){
//check if client is still connected
...
//read client message
while((RxLen=TCPRxLen(sock))>0)
{
TCPRead(sock,bff,RxLen);
strcat(msg,bff);
}
//write back to the client that the order is received
TCPWrite(sock, msg, strlen(msg));
//process the client order
...
//Write to the client that the process is done
TCPWrite(sock, msg2, strlen(msg2));
}
The java application read msg and msg2 with the first read(). msg and msg2 have "\r\n" at the end.
Doesn't somebody can tell me where I am wrong ?
Is there a function from BufferedReading that tells how much data there is left to read ?
Thanks and regards.
NB : I try with a small buffer in the java application, the problem is the same, read() is stuck when there is nothing left to read...
You're reading from the socket until end of stream, and you're never causing end of stream, as you are never closing the socket at the sender. Either close the socket or don't read until end of stream.

IOUtils copy and write issues

I'm trying to send strings to a server from a client but it doesn't seem to be reading from the input stream.
Client
Scanner scanner = new Scanner(System.in);
Socket connection = new Socket("localhost", 13)
OutputStream out = connection.getOutputStream();
while(true) {
String message = scanner.nextLine();
IOUtils.write(message, out, "UTF-8");
out.flush();
}
Server
ServerSocket server = new ServerSocket(localhost,13);~
Socket connection = server.accept();
InputStream in = connection.getInputStream();
StringWriter writer = new StringWriter();
while(true) {
try {
IOUtils.copy(in, writer);
System.out.println(writer.toString());
} catch(IOException io) {}
}
It reads if I close the stream from the client's outputstream but I am trying to send multiple messages from the client to the server. Could someone please help
You seem to think that each time you call flush() at client-side, the server will know it and be able to know that this is the end of a message. That's not the case. IOUtils.copy() reads everything from a stream of bytes. While the stream end hasn't been reached, copy() won't return.
You can see streams as two sides of a long tube. If you pour 10 buckets of water in the at the end of the tube, all you'll get at the other side is a continuous flow of water.
If you need multiple separate messages, then you need to design a protocol allowing to separate messages, and read until the end of a message has been reached. It could be based on separators for example. Or you could send the length of the message followed by the message itself, to let the server know how many bytes it must read to get the next message.

Categories

Resources