BufferedReader reading from socket - java

I have a bufferedreader and for some reason it wont read the text from the print stream I am sending from my client. This is the point at which it fails every time the line = in.readline
Also I have checked and the server is connected.
This is the error
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at Server.ServerListener$getXML.run(ServerListener.java:82)
at java.lang.Thread.run(Thread.java:662)
Thanks in advance
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
//PrintStream out = new PrintStream(server.getOutputStream());
System.out.println("Start");
//read the xml
boolean connected = server.isConnected();
System.out.println("xml: "+ connected);
line = in.readLine();
System.out.println("Postread");
while ((line = in.readLine()) != null) {
System.out.println("while1");
xml = xml + line;
System.out.println("while2");
}`

isConnected() tells you whether your socket is connected to the connection, not whether the connection is still connected to the peer. Obviously you aren't still connected at all. 'Connection reset' has several possible causes: you wrote to a connection that had already been closed by the other end (application protocol error); the other end aborted the connection; the local TCP stack has encountered network errors sending and has given up. First of those is then most likely suspect. And don't use PrintStreams/Writers across the network, as they swallow exceptions you need to know about. And you are throwing away a line of data with the first readLine() call: remove it and just leave the one in the loop.

Related

Buffered Reader for a socket is never ready

Just to be completely transparent, this is for an assignment.
There is more to do, but at the moment I'm just trying to get the following:
Node A reads in from a text file
Node A sends text file (minus the first line) to Node B using a socket
Node B read in from said socket, and prints it out to the console
However, right now, it seems that either the information isn't being sent, or it's not being read correctly by Node B.
In my main class, I set up the nodes like this:
NodeA nodeA = new NodeA();
NodeB nodeB = new NodeB();
new Thread(nodeA).start();
new Thread(nodeB).start();
In node A, I do this:
//Open a socket for talking with NodeB
Socket mySocket = new Socket(InetAddress.getLocalHost(), portNum);
//Set up the socket's output
PrintWriter out = new PrintWriter(mySocket.getOutputStream(), true);
//Loop through the lines of the confA file, writing them to the socket
String line = bufferedReader.readLine();
while (line != null)
{
//Write the line to the socket, get the next line
out.println(line); //updated to println, this flushes and fixes another problem
out.flush();
line = bufferedReader.readLine();
}
//Close the socket
mySocket.close();
Note that Node A's loop works fine. It doesn't loop forever and does go through the intended lines of text when I tested with print statements.
Then, on Node B's end: Updated to show current Node B code
//Open the socket
ServerSocket mySocket = new ServerSocket(portNum);
Socket connectionSocket = mySocket.accept();
//Set up a reader on the socket to get what's coming from it
BufferedReader in = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
String line = in.readLine(); //hang occurs here
while(line != null) {
System.out.println(line);
line = in.readLine();;
}
However, in.ready() is never true. I've tried waiting around for that to happen using a while loop but it never occurs.
I'm really not sure why. I have no idea if I set up the socket correctly, if I set up the server correctly, if I am listening correctly, etc.
I just figured that making B into a server which is listening for A made the most sense. I hope that's right. It looks similar to what I saw some other examples on SO did.
Thank you for any and all help. I'm extremely unfamiliar with sockets, ports, listening and otherwise, so forgive me if I don't understand your suggestions at first. I'll do my best to understand it as I go.
I refrained from adding the whole of the code to hopefully make it more readable and clear where the issue might be, but if you need more information just feel free to ask and I'll do my best to provide it.
The server must first get from the ServerSocket the Socket to the client.
connectionSocket = mySocket.accept();
The server thread will be sleep till a client causes it to accept the connectionSocket.
Then you can read from the connectionSocket. ready not being needed.
As this is an assignment, I leave the rest to you.
By the way a typical server would do:
for (;;) {
Socket socket = serverSocket.accept();
... pass the socket to a thread from a pool of threads
}
I think the problem is that ready just means that if you call a read, it won't block. You can see the code that gets executed if you look up the function on grepcode:
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/io/BufferedReader.java#BufferedReader.ready%28%29
A ready thread just means it's not going to block, which is useful when you want to ensure that your thread isn't going to get tied up, but doesn't really tell you if you have buffer or not.
What you want to do is perform the readline, as a blocking call, until the data is consumed. If you don't want this blocking your current thread, then spin off a new consumer thread specific for this reading that can block.
Also, make sure that you're ending your send communication with either a closed socket or flush to indicate to the consuming stream when it is complete. And you only need to socket accept once per open/close session.

BufferedReader in Java fails to trigger exception when trying to read from closed socket [duplicate]

This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 6 years ago.
I'm connecting a TCP socket and opening a buffered reader for I/O on that socket in its own thread, then reading data using readLine on the buffered reader:
try {
socket = new Socket(targetHost, targetPort);
ou = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
message = in.readLine();
...
process the data
...
}
} catch (Exception e) {
e.printStackTrace();
return;
}
This works fine as long as the connection is there. But when the other end of the TCP connection unexpectedly goes away, in about 75% of all cases, this thread never realises the other side has gone away, and any attempts to read from the buffered reader will simply yield a "null" string, but no exception is thrown, and I'm unable to shut the thread down because it doesn't know the other side has gone away. In about 25% of the cases, the thread is terminated (also without generating an exception) but that yields the desired outcome, I just need the thread to go away when the TCP connection drops.
I tried using this to figure out if the connection is alive:
boolean connected = socket.isConnected() && !socket.isClosed();
but that doesn't work, always returns true when the other side has gone away and the thread keeps on chomping.
Any ideas anyone?
The point is basically: "works as designed".
The reader returning null actually means: "no more data; I am done here".
See the javadoc:
Returns: A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
In other words: the socket going closed is seen as "normal" operation here; thus there is no exception. In other words: you have to change your code to check if the result to readLine() returns null; and if so, you know what the socket is gone.

Multiple messages same PrintWriter

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.

java - continuous data sending through Socket

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.

Android Socket getting exception while sending 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.

Categories