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.
Related
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.
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.
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);
}
}
I am creating some client-side socket software to read events from a server. (For example, streaming stock quotes).
PROBLEM: .read(b); is returning immediately with a value of -1. This causes an infinte loop and the phone becomes very hot. Additionally, all checks to s.isConnected(), isOpen(), isBound() return true. Essentially the socket looks connected. (This is an error scenario, so any value of .setSoTimeout(x) has no effect. 12 minutes, or leave empty. The .read(b) always returns -1 immediately).
When I write to it later, via the getOutputStream(), I receive an exception EPIPE (broken pipe).
Here's the core code (log statements/value checks omitted for brevity).
s.connect(new InetSocketAddress(host, port), CONNECT_TIMEOUT_MILLIS);
byte[] b = new byte[1024];
while (s.isConnected()) {
int bytesToRead = s.getInputStream().read(b);
if (bytesToRead <= 0) {
LOGGER.debug("no bytes read? trying again.");
continue;
}
processFrame(b);
}
If I cycle the 3g on the phone, it works fine. Sometimes it gets into this weird state.
Question
Am I doing something wrong? Is this the expected behavior? Is there existing code I could look at to show the right way to do socket programming on Android?
I use the following code without problem:
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
myLineProcess(line); //here you process you line result
}
good luck.
If read(byte[], ...) returns < 0, the peer has closed the connection, so you must close the socket and exit the loop. There will never be any more data.
Input streams are blocking, so the only way read(byte[], ...) can return zero is if you specify a zero length buffer or a zero length, depending on which overload you call. As you aren't doing that, it will never return zero.
Instead it will do exactly what it says in the Javadoc: either return -1 meaning EOS, or block until at least one byte of data is available.
Am I doing something wrong?
Almost everything. Your loop testing for <= 0 is completely pointless and completely incorrect. And so is testing isConnected(). That only tells you whether you ever connected this Socket. It doesn't change with the state of the connection. The return code of -1 tells you that. Your loop should read:
while ((bytesToRead = s.getInputStream().read(b)) > 0)
{
// do something with b[0..bytesToRead -1].
}
s.close();
Well i don't know whether this would be the appropriate answer for this, but still i will like to give you the code, which does works well every time.
Please keep it simple,
Try using InputStream, InputStreamReader, BufferedReader, OutputStream, PrintWriter.
Client Side:
Socket s = new Socket();
s.connect(new InetSocketAddress("Server_IP",Port_no),TimeOut);
// Let Timeout be 5000
Server Side:
ServerSocket ss = new ServerSocket(Port_no);
Socket incoming = ss.accept();
For Reading from the Socket:
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
boolean isDone = false;
String s = new String();
while(!isDone && ((s=br.readLine())!=null)){
System.out.println(s); // Printing on Console
}
For Writing to the Socket:
OutputStream os = s.getOuptStream();
PrintWriter pw = new PrintWriter(os)
pw.println("Hello");
Hello all my friends,
I am trying to send a long string through socket connection but I have them in two parts so I get an error while doing my processs.
In client I am sending the file,
BufferedWriter bufferedOut = null;
BufferedReader in = null;
socket = new Socket("192.168.0.15",4444);
bufferedOut = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
bufferedOut.write(xmlInString, 0, xmlInString.length());
/**
* wait for response
*/
byte[] buf = new byte[10000];
int actualNumberOfBytesRead = socket.getInputStream().read(buf);
String responseLine = new String(buf, 0, actualNumberOfBytesRead);
In the server,
BufferedReader in = null;
PrintWriter out = null;
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
//get the input
byte[] buf = new byte[10000];
int actualNumberOfBytesRead = client.getInputStream().read(buf);
line = new String(buf, 0, actualNumberOfBytesRead);
//send back
out.println(result);
How I can get my string as one part ? Can you please show me where is my mistake on the code ?
Thank you all
You will need a loop to repeatedly read from the input stream, concatenating the read data together each time, until you reach the end of the string.
Edit - a little more detail. If you are looking at transmitting multiple such strings/files, then see #arnaudĀ“s answer. If all your looking to to is send 1 big string then:
On the sender side, create the output stream, send the data (as you have done), and then don't forget to close the stream again (this will also perform a flush which ensure the data gets sent over the wire, and informs the other end that there is no more data to come).
On the recipient site, read the data in a loop until the input stream ends (read(buf) returns -1), concatenating the data together each time in one big buffer, then close the input stream.
Also, please read my comment about sending a file as bytes rather than a string. This is particularly important for XML files, which have rather special rules for encoding detection.
When using a TCP socket, you are handling "streams". That is, there is no delimitation between messages by default. By proceeding as you do, you may read part of a message, or worse, read more than a message.
The most common way to proceed is to delimit your messages. You can use DataInputStream/DataOutputStream which encodes strings into bytes and use the first bytes to indicate it's length. That way, it knows how many bytes it should read on the receiver end.
DataOutputStream out = null;
DataInputStream in = null;
Socket socket = new Socket("192.168.0.15",4444);
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
out.writeUTF(xmlInString);
out.flush(); // to ensure everything is sent and nothing is kept in the buffer.
// wait for response
String responseLine = in.readUTF();
Then, adjust the server code accordingly.
When using Buffered outputs with sockets, which is advised for performance reasons, it is advised to flush() after you wrote the message to ensure that everything is actually sent over the network and nothing is kept in the buffer.
Your initial problem probably occurred because your message requires several TCP/IP packets and in your server, you read only the first one(s) which just arrived.