BufferReader stucks when using read() - java

I have developed a small java client that suppose to communicate with a tool installed on unix-server.
I'm working with Socket first time so could do something wrong. I am also limited to Java 6.
In brief code looks like this
I use Socket to establish connection.
Socket socket = new Socket();
SocketAddress socketAddress = new InetSocketAddress(endpoint, port);
socket.connect(socketAddress, 5000);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Here is how I send message
out.println("Hello");
out.flush();
And here is how I read response
String res = "";
int letter;
while(letter = in.read() != -1) {
char c = (char) letter;
res += c;
}
F.x. If I send a message "Hello", I will receive answers with 2 lines (see example below)
> Hi there
> My name is Robot
The things stuck when I read next character after "Robot\n", I expected that in.read() != -1 will be true and thus it will stop itself, but that is not a case and instead everything just stuck.
What could be the reason to this and how to solve? Thanks.
Please let me know if I need to provide more information.

I had to close my output writer before reading from it, otherwise it blocks.
if (!socket.isOutputShutdown()) {
socket.shutdownOutput();
}
The answer came from a person who later deleted own answer :-/

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 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.

How to handle sending multiple messages over a socket connection?

I'm a bit of a beginner programmer so it's possible this is quite obvious and I'm overlooking the answer. But on to the question.
I have a two-part program (its a little more complicated than this example, but the situation is the same). The program has multiple messages fired between the client and the server. I have a PrintWriter on the server-side to send messages to the client, and on the client, I have a BufferedReader to read the messages sent.
When this example is run, I'm given two lines as output. The first message is both messages, and the second is NULL. What I am wondering is if there is a way to basically halt the server until I am ready for the second message, so that I can do something on the client-side before the second message is sent.
I am hoping to not use Thread.Sleep, as I would rather the Server wait around until the Client says it is ready.
This is the client:
public class Client{
public void run(){
Socket socket = null;
InputStream in = null;
BufferedReader reader = null;
try{
socket = new socket("LocalHost",1234);
in = socket.getInputStream();
reader = new BufferedReader(new InputStreamReader(in));
}
String messageFromServer = "";
try{
messageFromServer=reader.readLine();
}
System.out.println(messageFromServer);
String messageFromServer = "";
try{
messageFromServer=reader.readLine();
}
System.out.println(messagefromServer);
//close everything
}
}
This is the server:
public class Server{
public void run(){
ServerSocket server = null;
Socket client = null;
try{
server = new ServerSocket(1234);
client = server.accept();
}
PrintWriter writer = null;
OutputStream out = null;
try{
out = client.getOutputStream();
writer = new PrintWriter(out, true);
}
writer.write("Hi I'm a server");
//do some stuff that takes some time, user input, etc. etc.
writer.write("I'm still a server");
//close everything
}
Thanks :)
The problem with the way you currently have you code is the fact that you are using a BufferedReader, but the server is not terminating it's messages with a new line.
When you close the writer, the client is reaching the EOF or EOS and unblocking the read so it appears that both strings are being sent at once...
If you do something like...
writer.write("Hi I'm a server\n");
// This will force the message to be written to the client and picked up ;)
writer.flush();
writer.write("I'm still a server\n");
writer.flush();
Then you will get the messages seperatly...
You can use ObjectInputStream to read Objects instead of Strings.
This way you will read only one Message(String in your case) every call to ObjectInputStream.readObject();
BTW you can read the first message, "do something" and then read the second message. you don't have to read all of the sent messages at once.
If there are no other messages, then your thread will be blocked when trying to read an object from the ObjectInputStream.
Use it like:
ObjectInputStream inputStream = new ObjectInputStream( socket.getInputStream() )

Better ways than BufferedReader.readLine()?

Using ServerSocket and BufferedReader.readLine() the input is only read once the line is terminated on the client side, is there anyway to read the input, and send an output before the line is terminated?
ServerSocket SRVSOCK = new ServerSocket(35553);
while(true){
Socket SOCK = SRVSOCK.accept();
InputStreamReader IR = new InputStreamReader(SOCK.getInputStream());
BufferedReader BR = new BufferedReader(IR);
String MESSAGE = BR.readLine();
PrintStream PS = new PrintStream(SOCK.getOutputStream());
System.out.println(MESSAGE);
PS.print("Returned Successfully");
}
You could go with bufferedReader.read() which will return the values one character at a time
StringBuffer response = "";
while ((c = bufferedReader.read()) != -1)
{
//Since c is an integer, cast it to a char. If it isn't -1, it will be in the correct range of char.
response.append( (char)c ) ;
}
If you go with this method, it's up to you to figure out when you can start parsing the result and send a reply.
Have a look at this answer.
You can read input into a buffer whose size is under your control.
(Apologies if linking to self answers is considered bad. Felt like reusing it. We are devs after all.)

Reading Java sockets - either receiving duplicate lines or loss

I am having a field day trying to figure out why my Java code is not working.
I am supposed to receive the following messages from a C program via sockets.
1~message~i love you\r\n
2~message~do you love me?\r\n
3~message~when are we going to meet again?\r\n
4~message~How about now?\r\n
5~message~Oh! I'm pregnant!\r\n
Instead, I am receiving the following messages instead.
1~message~i love you\r\n
2~message~do you love me?\r\n
2~message~do you love me?\r\n
5~message~Oh! I'm pregnant!\r\n
I ran a port redirector on my laptop and found out that the C program is transmitting the messages correctly. It's my Java program that is not receiving them properly.
I am using Java NIO Channels to receive the messages.
My code as follows:
StringBuffer stringBuffer = new StringBuffer();
int pos = 0; // position of Buffer
// initialize server and client sockets
ServerSocketChannel serverChannel = null;
SocketChannel clientChannel = null;
// initialize ByteBuffer
ByteBuffer inBuffer = ByteBuffer.allocateDirect(65536);
inBuffer.order(ByteOrder.LITTLE_ENDIAN);
try {
serverChannel = ServerSocketChannel.open();
SocketAddress port = new InetSocketAddress(8080);
serverChannel.socket().bind(port);
while (true) {
clientChannel = serverChannel.accept();
while ((bytesRead = clientChannel.read(inBuffer)) != -1) {
inBuffer.flip();
while (inBuffer.get(pos) != '\r') {
stringBuffer.append((char) inBuffer.get(pos));
pos++;
} // end while loop checking for bytesRead
//increment over \r and \n
inBuffer.get();
bytesRead--;
inBuffer.get();
bytesRead--;
pos = pos + 2;
System.out.println(stringBuffer);
stringBuffer.setLength(0);
pos = 0;
} // close while reading bytesRead loop
} // close while(true) loop
} catch (IOException ex) {
}
I suggest you try plain IO which is simpler for this use case.
ServerSocket serverSocket = new ServerSocket(8080);
while(!serverSocket.isClosed()) {
Socket socket = serverSocket.accept();
System.out.println("Accepted socket "+socket);
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
StringBuilder sb = new StringBuilder();
int b;
while((b = bis.read())>=0) {
if (b == '\r')
b = bis.read();
if (b == '\n') {
System.out.println(sb);
sb.setLength(0);
} else {
sb.append((char) b);
}
}
System.out.println("Closing socket.");
socket.close();
}
Do you have to use NIO for this? It's generally a lot harder to get right (at least for me). My guess is that the problem is that you're always reading, but you're calling flip exactly once per read... whereas I'd expect to see two flips, or possibly a flip before the read and then a clear at the end of the processing.
Note that you're also completely ignoring bytesRead - why bother decrementing a variable which you're then reassigning without reading?
Furthermore, you're assuming you get exactly one \r from each read call. What if you receive two lines in one call, or one imcomplete line?
I'm not qualified to give the correct NIO code, but I'd recommend that you try to get it working with a plain InputStream first and then move onto NIO.
SocketChannel.read puts data into the buffer at the buffers current position. You're iterating the buffer from position 0 every time.
If you get two lines in one read you're only handling up to the first \r and then continuing by reading again. You may miss the final lines this way.

Categories

Resources