How to send reply from TCP server to TCP client? - java

I have following code for server and client. Client is able to send data to Server successfully but when Client tries to read data from server, code keeps on running without any output.
Server:
public static void main(String[] args) throws Exception {
ServerSocket s = new ServerSocket(9898);
while(true) {
Socket recv = s.accept();
InputStream inp = recv.getInputStream();
OutputStream out = recv.getOutputStream();
String data = null;
BufferedReader in = new BufferedReader(new InputStreamReader(inp));
while ( (data = in.readLine()) != null ) {
System.out.println("\r" + data);
}
out.write("sampleSendToClient".getBytes());
}
}
Client:
public static void main(String[] args) throws Exception{
Socket clientSocket = new Socket("localhost", 9898);
OutputStream out = clientSocket.getOutputStream();
InputStream inp = clientSocket.getInputStream();
out.write("sampleSendToServer".getBytes());
String data = null;
//if I dont write next 4 lines then client exits gracefully
//but now it is stuck infinitely
BufferedReader in = new BufferedReader(new InputStreamReader(inp));
while ( (data = in.readLine()) != null ) {
System.out.println("\r" + data);
}
clientSocket.close();
}
I am unable to understand what is wrong in above code.

Quick but painless your server writes directly on the output stream by calling OutputStream#write(byte[] data) but your clients reads with a BufferedReader and BufferedReader#readLine() is a blocking I/O operation which will suspend his thread until a \n or \r character arrives on the InputStream (or the stream is closed in which case the method gets intererrupted an null is returned).
The String your server is sending does not end with \n or \r so the data may be sent already and linger in the buffere of the client's BufferedReader but without either of those terminating characters readLine() will never return.
Simply change
out.write("sampleSendToClient".getBytes());
to
out.write("sampleSendToClient\n".getBytes());
should do the trick.
Update:
while ( (data = in.readLine()) != null ) {
System.out.println(data);
}
This while loop will only exit if readLine() returns null this will only be the case if the stream is clsoed. However since you can't close the streams without losing the connection you will have to find another way to terminate the loop because now it will run forever.
Even after adding the \n your server wouldn't respond because he wil be infinitely loop at that point.
On a side note: For each new connection you're overwriting the previous socket without closing it's resources (primarly focused on the data stream and sockets themselves) and therefore creating ressource leaks. Consider to close every object when they are no longer needed.

Related

Java bufferedReader readline loop does not break

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.

Has BufferedReader a Timeout when sending HTTP Get Request?

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.

Read data from a Java Socket

I have a Socket listening on some x port.
I can send the data to the socket from my client app but unable to get any response from the server socket.
BufferedReader bis = new BufferedReader(new
InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = bis.readLine()) != null)
{
instr.append(inputLine);
}
This code part reads data from server.
But I can't read anything from server until unless the Socket on the server is closed.
Server code is not under my control to edit something on it.
How can I overcome this from client code.
Thanks
Looks like the server may not be sending newline characters (which is what the readLine() is looking for). Try something that does not rely on that. Here's an example that uses the buffer approach:
Socket clientSocket = new Socket("www.google.com", 80);
InputStream is = clientSocket.getInputStream();
PrintWriter pw = new PrintWriter(clientSocket.getOutputStream());
pw.println("GET / HTTP/1.0");
pw.println();
pw.flush();
byte[] buffer = new byte[1024];
int read;
while((read = is.read(buffer)) != -1) {
String output = new String(buffer, 0, read);
System.out.print(output);
System.out.flush();
};
clientSocket.close();
To communicate between a client and a server, a protocol needs to be well defined.
The client code blocks until a line is received from the server, or the socket is closed. You said that you only receive something once the socket is closed. So it probably means that the server doesn't send lines of text ended by an EOL character. The readLine() method thus blocks until such a character is found in the stream, or the socket is closed. Don't use readLine() if the server doesn't send lines. Use the method appropriate for the defined protocol (which we don't know).
For me this code is strange:
bis.readLine()
As I remember, this will try to read into a buffer until he founds a '\n'. But what if is never sent?
My ugly version breaks any design pattern and other recommendations, but always works:
int bytesExpected = clientSocket.available(); //it is waiting here
int[] buffer = new int[bytesExpected];
int readCount = clientSocket.read(buffer);
You should add the verifications for error and interruptions handling too.
With webservices results this is what worked for me ( 2-10MB was the max result, what I have sent)
Here is my implementation
clientSocket = new Socket(config.serverAddress, config.portNumber);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while (clientSocket.isConnected()) {
data = in.readLine();
if (data != null) {
logger.debug("data: {}", data);
}
}

buffered reader not receiving data from socket

I am writing a client application that will receive a continuous flow of data through tcp/ip. The problem I'm having is that the buffered reader object isn't receiving any data and is hanging at the readline method.
The way the server works is that you connect to it, and then send authentication information in order to receive data. The gist of my code is below
socket = new Socket(strHost, port);
authenticate();
inStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
process(inStream);
authenticate()
{
PrintWriter pwriter = new PrintWriter(socket.getOutputStream(), true);
pwriter.println(authString);
}
process(BufferedReader bufferedReader)
{
while((line = bufferedReader.readLine()) != null)
dostuff
}
I created a sample server application that sends data the way (I think) the server is sending data and it connects, and receives and processes the data fine. I can connect to the server fine in my application. I can also telnet to the server and write the authentication string and receive a flood of data using telnet. However my application just hangs at readLine with the server and I'm out of idea's why.
The data coming in (through telnet atleast) looks like a continuous stream of the following:
data;data;data;data;data
data;data;data;data;data
Why is my app hanging at readline, am I not outputting the authentication line correctly? I'm not receiving any errors...
EDIT
My sample server code (which is working correctly)...again this is only mimicking the way I think the real server is running but I can connect to both in my application just not receive data from the real server.
public static void main(String[] args) throws IOException
{
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(1987);
}
catch (IOException e)
{
System.out.println("Couldn't listen on port: 1987");
System.exit(-1);
}
Socket clientSocket = null;
try
{
clientSocket = serverSocket.accept();
}
catch (IOException e) {
System.out.println("Accept failed: 1987");
System.exit(-1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String something;
while ((something = in.readLine()) != null)
{
while(true)
{
out.println(message);
}
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
Firstly you should call BufferedReader.ready() before calling readLine(), as the ready() will tell you if it's ok to read.
PrintWriter doesn't throw I/O Exception so the write may have failed without your knowledge which is why there is nothing to read. Use PrintWriter.checkError() to see if anything as gone wrong during the write.
You ought to set up the input and output streams on the Socket at the same time before you write anything down the pipe. If your reader is not ready when the other end tries to write you will get a broken pipe in the server and it won't send any more data. Telnet sets up read and write before you have written or read anything.
You can make use of Wireshark to tell if the server is actually sending data.
BufferdReader.readLine() reads lines, i.e. sequences of characters ended with \r or \r\n. I guess that your server writes its output into one single line. Your telnet output proves this assumption. Just use PrintWriter.println() at server side.
this work with me
with socket without flush
void start_listen()
{
String result1="";
char[] incoming = new char[1024];
while (!s.isClosed())
{
try {
int lenght = input.read(incoming);
result1 = String.copyValueOf(incoming,0,lenght);
}
catch (IOException e)
{
e.printStackTrace();
}
Log.d("ddddddddddd",result1);
}

server client communication java

I have this client, the server information is not important. The output of this code is very random.
class Client {
public static void main(String args[]) throws Exception
{
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("127.0.0.1", 10004);//this will become the addr of the server you want to input.
InetAddress host = clientSocket.getInetAddress();
// System.out.println(host);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
boolean exit = false;
while (!exit) {
while (inFromServer.ready()) {
System.out.println(inFromServer.readLine());
}
String sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + "\n");
}
clientSocket.close();
}
}
If I run this in debug mode, it has always the correct result. E.g.
please insert password
the user types pass
pass correct
please type command
and you type command
etc
etc
When it's not in debug mode, all goes wrong. I don't even get the initial request from server. What is going on? I think the read line might be executed too fast?
in.ready() does not wait for any data to be available. It the server hasn't sent the data yet when you client reads that line, you're going to skip the readLine() completely.
Just remove that while and do a plain readLine().
If there are phases where you need to wait for multiple lines from the server, you'll need to implement more logic. Usually, the server will send an "end of message" marker to signify to the client that it is done. For example, when the server is done, it could send the message "END-OF-MESSAGE". In the client code, you would do:
boolean serverDone = false;
while (!serverDone) {
String message = in.readLine();
if (message == null) {
// handle this problem: the server has closed the connection
serverDone = true; // or return, or throw
} else if ("END-OF-MESSAGE".equals(message)) {
serverDone = true;
}
}

Categories