I'm using java and sockets to comunicate a client/server application.
I want to send a message to server like this:
is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
pw = new PrintWriter(socket.getOutputStream());
pw.println("MESSAGE");
pw.flush();
And that worked well, but then after that I'm trying to send another message
pw.println("SECOND MESSAGE");
pw.flush();
And the second message is not sending! What can I do?
Ensure that your server side is consistently reading for more input. If you only have it say for example performing:
bufferedReader.readLine();
only once then this is the reason you think it isn't receiving it. It probably is if the connection isn't closed.
Another possibility since you said it isn't "sending" the second message, is ensure the socket connection remains open and that the reader is still open on the server side and that it wasn't closed after the first message was received.
use flush() when all the messages are sent.
Related
is there a way of knowing when or whether the flush() method of a BufferedOutputStream thread has finished successfully? In my case I'm using it for sending a simple string through a java.net.Socket. In the following code, the flush() method is run in parallel with the BufferedReader.read() method and the socket output is immediately blocked by the input read resulting in something that resembles a deadlock. What I would like to do is wait for the output to end, and then start reading the input.
Socket sk = new Socket("192.168.0.112", 3000);
BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
bo.write(message.getBytes());
bo.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String line = br.readLine();
if (line.equals("ack")) {
System.out.println("ack");
}
sk.close();
Update
ServerSocket:
ServerSocket ss = new ServerSocket(3000);
System.out.println("server socket open");
while (true) {
Socket sk = ss.accept();
System.out.println("new connection");
BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String line = br.readLine();
System.out.println("received line: " + line);
BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
bo.write("ack".getBytes()); bo.flush();
sk.close();
}
Update:
#Global Variable - the reason that read was blocking the socket is that it was waiting for the \n, indeed. Using
bo.write("ack\n".getBytes());
instead of
bo.write("ack".getBytes());
made it work.
Regarding the initial question, is there a way of knowing if flush() method has finished successfully, #Stephen C provided the answer:
there is no way to know that based on the Socket or OutputStream APIs.
The normal way to get that sort of assurance is to have the remote
application send an "reply" in response, and read it in the local
side.
This "reply" is implemented in the code sample and it works.
Is there a way of knowing when or whether the flush() method of a BufferedOutputStream thread has finished successfully?
It depends on what you mean by "finished successfully".
The flush() method ensures that all unsent data in the pipeline has been pushed as far as the operating system network stack. When that is done, then you could say that flush() has finished successfully. The way that you know that that has happened is that the flush() call returns.
On the other hand, if you want some assurance that the data has (all) been delivered to the remote machine, or that the remote application has read it (all) ... there is no way to know that based on the Socket or OutputStream APIs. The normal way to get that sort of assurance is to have the remote application send an "reply" in response, and read it in the local side.
In the following code, the flush() method is run in parallel with the BufferedReader.read() method and the socket output is immediately blocked by the input read resulting in something that resembles a deadlock.
The code that you are talking about is basically the correct approach. The way to wait for the response is to read it like that.
If it is not working, then you need to compare what the client and server side are doing:
Is the server waiting for the client to send something more? Maybe an end of line sequence?
Did the server sends the response?
Did it flush() the response?
A mismatch between what the client and server are doing can lead to a form or deadlock, but the solution is to fix the mismatch. Waiting for some kind of hypothetical confirmation of the flush() is not the answer.
UPDATE
The problem is indeed a mismatch. For example, the server writes "ack" but the client expects "ack\n". The same happens in the client -> server case ... unless message always ends with a newline.
Your code is reading reader.readLine() . Are your writing \n when writing? You may want to append \n to the string your are writing.
I tried to reproduce your problem. First, I ran in to some kind of blocking state too, until I realized, I was using readLine at Server-side, too. But the message I was sending did not have a concluding \n. Therefore, the serversocket was still waiting at its InputStream without sending the client the ACK through its OutputStream. I think, #Global Variable is right.
I'm writing a Java client/server application. It should allow clients to send text data to the server. This kind of communication should be repeatable many times using the same connection.
I write it like this:
// On a server:
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
socket.setKeepAlive(true);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
if (reader.ready()) {
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
// do something with line
}
}
// On a client:
Socket socket = new Socket(host, port);
socket.setKeepAlive(true);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write("Some data from client to server");
writer.flush();
The problem is: I can't read on a server before I close OutputStream on a client. Or I can't open OutputStream on a client again, if it was already closed. How can I do continuous sending and reading of data?
You need two threads at both ends, one for reading data and other one for writing data.
The problem is: I can't read on a server before I close OutputStream on a client.
Yes you can. You just can't get to the case where readLine() returns null. It isn't the same thing.
Or I can't open OutputStream on a client again, if it was already closed.
Of course not. You have to create a new Socket.
How can I do continuous sending and receiving of data?
I don't understand the question. The code you posted doesn't attempt that.
If your goal is to send many mesages over the same socket connection, these messages will have to be delimited by an application-level protocol. In other words, you won't be able to rely on any system calls like reader.ready() or reader.readLine() == null to detect the end of the message on te server.
One way to achieve this is to begin each message with its length in characters. The server will then read exactly that number of charecters, and then stop and wait for a new message. Another is to define a special character sequence which concludes each message. The server will react to reading that particular sequence by ending the reading of the current message and returning to the "wait for new message" state. You must ensure that this sequence never appears in the message itself.
I am trying to send xml to an IP. I am doing that with following code:
String sMessage = "<SERVER><CONNECT><IP>192.168.10.14</IP><CLIENT_ID>123</CLIENT_ID></CONNECT></SERVER>";
Socket socket = new Socket("192.168.252.148", 34543);
System.out.println("socket connected---: "+socket.isConnected());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
InputStream in = socket.getInputStream();
out.println(sMessage);
byte[] buffer = new byte[in.available()];
in.read(buffer);
String rMsg = new String(buffer);
System.out.println("rMsg: "+rMsg);
out.close();
in.close();
socket.close();
rMsg is always empty. socket connection is true. Why am i not getting response back. I tried to change InputStream to BufferedInputStream but it did not help. Any idea to solve this problem by either fixing this code or by having new idea? Thanks in advance.
I'm afraid I don't really understand what you are trying to do. Your sending an XML file to an address, fair enough, but why are you automatically assuming the destination knows how to understand and create an XML formatted reply? What is the server-side implementation?
If there is such an implementation and you are not receiving data, then there must be a problem on that end, could you post code from it?
What should the server send you back? The thing is that you send an XML to the server and want to receive input at the same time from the server. But the response from the server may take some time. But I guess at this point your inputstream is closed or you are not listening to that any more. One simple solution to check that will be to put everythin in a while loop so you will see if your server answers (a bit later)... you also can listen to the NIC of your server with wireshark. Perhaps your server doesn't send anything?
I got server-client application. On the client side, I am using this I/O stream to output data:
out = new PrintWriter(socket.getOutputStream(), true);
out.println("yeah");
On the server side I am trying to read the product by this line:
DataInputStream din = new DataInputStream(s.getInputStream());
String clientId = din.readUTF();
The server reaches the above statement and stops there. What's the problem? Are the two I/O streams not compatible with each other?
There are no exceptions thrown by either party, no output. I simply added System.out.println() before and after the above statement I=and I determined that the program does not cross this line:String clientId = din.readUTF();
You should use the DataOutputStream.writeUTF() method if you want to read from the other end of the socket with DataInputStream.readUTF(). See the Javadoc on DataInput for more detail on why. As an alternative, try using a buffered reader or scanner to read in your data.
I have tested the code below. It was working in emulator but not working in Android Mobile. Do I need to do any settings? Please help me.
Thank you.
try {
Socket socket = new Socket("192.168.0.54", 9083);
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
out.println("Testing");
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(
inputStream));
String readObject = reader.readLine();
System.out.println(readObject);
}
catch (Exception e) {
e.printStackTrace();
}
"Connection reset by peer" means that someone between your phone and the server (inclusive) closed the connection while you were reading it.
First check if the server receives and sends anything. If not, then someone between your phone and the server is blocking the transfer. If you are on corporate WiFi, there may be firewalls prrotecting the server etc. If on 3G there definitely is one.
You should add the stack trace to your post. Without it our answers are just guesswork...
Edit: The IP address 192.168.x.x points to an internal network. Are you sure you can access the internal network from WiFi/3G?
'Connection reset by peer' is usually caused by writing to a connection that has already been closed by the other end. In other words, an application protocol error. It doesn't show up on that write, but on a subsequent I/O operation.