I use the following code to output HTTP request message. But the loop never ends after outputing HTTP request from browser. It seems that bufferReader just waiting for new bytes after outputing HTTP request.
InputStream inputStream = socket.getInputStream(); // socket is returned by
// serverSocket.accept()
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
// output HTTP request
String line;
while ((line = bufferedReader.readLine()) != null) { // the loop never ends
System.out.println(line);
}
I agree with mhasan. If you know ahead of time the expected length of the message, you can read that many bytes and then explicitly exit the loop.
See the code examples in this answer: https://stackoverflow.com/a/19863726/2751039
This is happening because the peer connection is never getting closed.
If it never closes, readLine() won't return null.
Related
In my java code, I send a string through socket to another stream.
Sender code:
OutputStream out = socket.getOutputStream();
String u = new String("something as text");
PrintWriter p = new PrintWriter(out);
p.print(resultMessage);
p.flush();
p.print("\0");
p.flush();
Reciever Code:
String s;
while ((s = br.readLine()) != null ) {
System.out.println(s);
}
System.out.println("DONE");
The problem is that after printing the data it recieved, the while loop does not stop and will be stock in while ((s = br.readLine()) != null ). So It does not print Done
If you don't close the connection, there will not be an end-of-stream and the other side will wait forever (unless a read timeout is configured).
If you've finished sending all the data you need, close the socket. Otherwise the receiving end will wait for any other data you might be sending.
Sending NUL (\0) doesn't do anything special, it definitely won't result in null being read by readLine().
If you want to keep sending data back and forth, with something happening in between, you need to come up with a protocol to use (i.e. what kind of messages are being sent and when), and design your program starting from there.
I'm trying to read a HTTP request using only Socket and BufferedReader classes in Java. The problem is that I can't reach the body part of the request. The Buffered reader is giving me only the request line and the headers. Here is part of the code:
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String comando = "";
while((msgDoSocket = bufferedReader.readLine()) != null){
//telaOutput.adicionaFim(msgDoSocket);
try {
comando += msgDoSocket + " ";
//System.out.println(comando);
if(msgDoSocket.isEmpty()){
processaInput(comando);
}
} catch (Exception ex) {
Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
Here is a WireShark capture showing that the POST body is being sent. My program is running on port 15000 and the data is just a string "teste12345". I'm using the app POSTMAN from google chrome to send the requests.
I'm having exactly the same problem described in this thread but the solutions proposed there didn't work. The request still getting up to the last header and no more. Thanks in advance.
Edit: Problem Solved!
Following suggestion proposed on the answer, I changed the reading to:
reader = new DataInputStream(socket.getInputStream());
String comando = "";
while( (dt = reader.readByte()) >= 0){
comando += dt;
//... do the rest of the stuff
}
Reading it as binary made it possible to reach the body part of the request.
I'm far from being a Java guru, but I bet that readLine only returns with results when it found a sequence of \r\n. since your body is not terminated with \r\n the method readLine never returns. try to manually add that character sequence to your body and see what happens, or alternatively, use the raw InputStreamReader to read the body as byte array.
never the less, you can't expect any http body to actually be a string. it can also be a binary sequence which knows nothing about \r\n.
I am using a socket to send HTTP GET request in order to control a Signal Generator via SCPI commands.
I manage to send several request and receive answer from the server.
My problem is if I wait about 15 seconds, then I send requests again, I do not receive any answer to my requests. It seems the BufferedReader does not received any message anymore
I have set the timeout of my socket to infinite. It seems my problem comes from a "timeout" of the BufferedReader as his ready method returns always false.
The only solution to receive message again is to close and re-create my Socket, PrintWriter, and BufferedReader.
I declare my socket and PrintWriter and BufferedReader as below:
tcpIpSocket = new Socket(ipAddress, tcpPort);
printWriteOutputStream = new PrintWriter(tcpIpSocket.getOutputStream(),false);
bufferInputStream = new BufferedReader(new InputStreamReader(tcpIpSocket.getInputStream()));
I use a seperate function to send and received my HTTP GET request as folow:
public static String sendRequestToSigGenerator(String scpiMessageToSend) throws Exception {
StringBuffer receivedHTTPMessages=new StringBuffer();
int receivedCharacterFromInputStreamInt;
printWriteOutputStream.println("GET /;:"+scpiMessageToSend+ " HTTP/1.0\r\n");
printWriteOutputStream.flush();
Thread.sleep(100); //Sleep needed for the buffer to be filled
while (bufferInputStream.ready()) {
receivedCharacterFromInputStreamInt = bufferInputStream.read();
receivedHTTPMessages.append((char)receivedCharacterFromInputStreamInt);
}
return(receivedHTTPMessages.toString());
}
After not sending message for 15 seconds and sending a new request, the while (bufferInputStream.ready() stays always false
EDIT:
Instead of implementing my own HTTP, I use the library : java.net.URL; which handle easily my queries and avoid my problem:
public static String sendHTTPRequest(String scpiCommand) throws Exception {
try{
StringBuilder returnString= new StringBuilder();
URL url = new URL("http://"+ipAddress+"/;:"+scpiCommand);
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
String strTemp = "";
while (null != (strTemp = br.readLine())) {
returnString.append(strTemp);
}
return(returnString.toString());
} catch (UnknownHostException e) {
return ERROR;
} catch (IOException e) {
return ERROR;
}
}
It seems my problem comes from a "timeout" of the BufferedReader
No. There is no such thing.
as his ready method returns always false.
Which merely means that no data has arrived yet. It is your expectations that are at fault here. Instead of the pointless sleep() and the equally pointless ready() test, you should just block inread() until data arrives or EOS or an exception occurs.
If you don't want to block forever , set a read timeout on the socket. Don't turn off the mechanism you actually need and then try to reproduce it by other means.
I am working on a simple programm for a university course. Here is the code that I have problems with:
//everything before this is unrelevant
String message = "";
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while((message = br.readLine()) != null) {
System.out.println(message);
}
//everything after this is irrelevant
I also have a thread for accepting incoming connections and some other stuff that is irrelevant. The problem that I have is that I can read one message and after that nothing happens. I guess the readLine() method is the problem but I am not really sure how to solve it.
It even says in our assignment to use
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
to receive data.
Your client is only sending one line. You therefore don't need the loop. You should read one line and then do whatever you're supposed to do with it.
I want to HTTP GET the server ,read the data and then again do HTTP GET or POST over same socket connection.
However I am unable to get a response for second request.What can be wrong with following code :
Socket s = new Socket(InetAddress.getByName("xyz.abc.asd"), 80);
InputStream is=s.getInputStream();
OutputStream os=s.getOutputStream();
PrintWriter pwGET = new PrintWriter(os);
pwGET.println("GET /login/ HTTP/1.1");
pwGET.println("Host: xyz.abc.asd");
pwGET.println("Connection: keep-alive");
pwGET.println("");
pwGET.flush();
BufferedReader brGET = new BufferedReader(new InputStreamReader(is));
String t=null;
while((t = brGET.readLine()) != null) {
System.out.println(t);
}
pwGET.println("GET /login/ HTTP/1.1");
pwGET.println("Host: xyz.abc.asd");
pwGET.println("Connection: keep-alive");
pwGET.println("");
pwGET.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
t=null;
while((t = br.readLine()) != null) {
System.out.println(t);
}
The main error is, that you don't parse the response correctly.
The response consists of an HTTP header followed by the body (maybe). To get the body you must parse and understand the response header, especially the code (some codes don't have a body), Transfer-Encoding and Content-length. Then you should also have a look at the Connection header.
Only then you know the length of the body and if further requests are accepted on this connection.
Apart from that lines should be delimited by \r\n, not just \n as you do with println.
In summary: if you really want to implement HTTP on your own study the necessary documentation (RFC2616 or the newer RFC7230..RFC7235). If you don't like this use existing HTTP libraries.