Unable to read data from InputStream - java

I'm trying to learn java socket programming, but I have a trouble with the read function of InputStream.
At first, I created a socket to connect to the server. After the connection is established, the server then send back the message that "the connection is established" and the read function is work fine. Then I tried to send byte message to the server, but I can't read the data from the InputStream because my program is stuck at "in.read(buf)" line. Could anyone point me out how can I solve this issue.
Socket client = new Socket("xxx.xxx.xxx.xxx", 45000);
InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();
for (int i = 0; i < 5; i++) {
byte[] buf = new byte[1024];
int data_size = in.read(buf);
String msg = "";
for (int j = 0; j < data_size; j++) {
msg += String.valueOf((char) buf[i]);
}
System.out.println(msg);
out.write(65);
out.flush();
}

InputStream.read() is a blocking call. Given the code you have provided, you are reading from the socket before writing to the socket so you will block on the first read forever. Or at least until the timeout.

#Peter Could be right. Also, closing the streams after their usage might help avoiding unexpected issues.

Related

Java socket input stream blocks

I've came across a problem and it's been bothering me for quite a time now. I'm working on a web server and the problem is that when i try to read the client request, the read() method blocks and waits for more bytes to read but there is none and the end of stream is reached which normally read() methods should retutn -1 but it won't until i hit the stop loading button on the browser.
ServerSocket ss = new ServerSocket(3000);
Socket s = ss.accept();
InputStream in = s.getInputStream();
int i;
while((i = in.read()) != -1){
//some processing here
}
How can i fix this problem? thank you very much

Java forcing a TCP socket to send data immediately

I read this question and other questions related to this but did not get any direct answer.
I need to send data to the client immediately for performance issue. I don't need Nagle's algorithm to efficiently send data.
Socket sock = new Socket("localhost", 1234);
sock.setTcpNoDelay​();
OutputStream output = sock.getOutputStream();
for(int i = 0; i < 100; i++){
output.write(dataByteArray);
output.flush();
Thread.sleep(delayTime);
}
My question is: as I have set sock.setTcpNoDelay​() do I really need to use output.flush() to request OS to send network buffer data immediately?

SSLSocket client doesn't throw exception if server is shutdown when writing to OutputStream

EDIT:
I have changed the code so that the integrity of the file is checked after the transfer.
But now when I put a breakpoint in the client at dos.write(buffer, 0, count), kill the server, and then resume client code execution, it hangs at serverMD5[i] = dataInputStream.readByte() indefinitely.
Even though the user now knows that the transfer was not successful (the application hangs and needs to be restarted), once again this is not doing what I expected it to do (throw an IOException).
Original post with changed code:
I have created an android client that connects to a server using SSLSocket and sends some data.
Here is the relevant client and server code
Client:
try {
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket();
sslsocket.connect(new InetSocketAddress(SERVER_IP, UPLOAD_PORT), 2000);
OutputStream outputStream = sslsocket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeInt(DEVICE_ID);
dataOutputStream.writeLong(FILE_LENGTH);
MessageDigest md = MessageDigest.getInstance("MD5");
DigestOutputStream dos = new DigestOutputStream(outputStream, md);
InputStream readingsInputStream = new FileInputStream(FILE_NAME);
int count;
byte[] buffer = new byte[10 * 1024];
while ((count = readingsInputStream.read(buffer)) > 0) {
dos.write(buffer, 0, count);
}
readingsInputStream.close();
byte[] md5 = md.digest();
byte[] serverMD5 = new byte[16];
DataInputStream dataInputStream = new DataInputStream(sslsocket.getInputStream());
for (int i = 0;i<16;i++) {
serverMD5[i] = dataInputStream.readByte();
if (md5[i] != serverMD5[i]) throw new Exception("MD5 mismatch");
}
sslsocket.close();
} catch (Exception e) {
...
}
Server:
try {
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
InputStream inputStream = sslSocket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
int deviceID = dataInputStream.readInt();
long fileLength = dataInputStream.readLong();
MessageDigest md = MessageDigest.getInstance("MD5");
DigestInputStream dis = new DigestInputStream(inputStream, md);
OutputStream readingsOutputStream = new FileOutputStream("Device"+deviceID+".txt", false);
int count;
byte[] buffer = new byte[1];
do {
count = dis.read(buffer);
readingsOutputStream.write(buffer, 0, count);
fileLength -= count;
} while (fileLength > 0);
readingsOutputStream.close();
byte[] md5 = md.digest();
DataOutputStream md5OutputStream = new DataOutputStream(sslSocket.getOutputStream());
for (int i = 0;i<16;i++) md5OutputStream.writeByte(md5[i]);
sslSocket.close();
} catch (Exception e) {
...
}
Normally this all works as expected but the problem occurs when I put a breakpoint in the client at the line dos.write(buffer, 0, count) and then kill the server upon reaching the breakpoint.
After continuing code execution on the client, it doesn't throw an exception and just goes through the rest of this code block, leading me to believe that the file was successfully written to the server.
Of course this is not the case since the server was shutdown before the OutputStream was written to. This results in an empty DeviceX.txt (X being the number of the device) file on the server.
This is a big problem since the user might think that the data was successfully transferred and delete it from the device (the data that is sent gets deleted at some point after due to the nature of the application).
Since I have managed to produce this bug I figure it is a possibility that it will happen in a real-world scenario as well. This is my first time working with sockets and I am at a loss as to what to do to fix this issue.
Also if anyone notices anything else that could go wrong with this code block (another scenario where the result is not as expected but an exception isn't thrown) please let me know.
This is normal operation of TCP. Leaving SSL aside, your sends are buffered in the socket send buffer, and transmitted asynchronously after the send() function has returned. It is therefore impossible for the send() function to detect a peer outage immediately. If you keep sending, TCP's retries of the pending data will eventually fail and cause a subsequent send to fail, in the case of Java with an IOException: connection reset.
inputStream.read(deviceIDbuffer);
You can't assume that read() fills the buffer. You should use DataInputStream.readInt() here.
Looks like you need two way communication between your client and server. when the client has completed the upload you could get the client to send an end of transmission (ascii 0x4) character (or any other character(s) that your client/server deems to be a "special" sequence). When the server has received an end of transition character the server could reply with the number of bytes it got. On the client side, wait for the response and if a timeout is reached, tell the user that something went wrong.

One-way connection between android tablet, router and 2 devices

I've got question, that I haven't found answer for yet. I have 2 devices with wifi each, that are sending special data. I want to show this data at the same moment on a tablet. There is a router with network, both tablet and that devices are connected to this network.
How to solve this? Should I use serversocket? I don't know if I explained it clear enought, if not, please ask. Thanks for any response.
I have the same application running on the company I work.
The "device" is a micro-controller based device that is implemented the lwIP (lightweight IP protocol) and it's listening to the port 83 and every 500ms the tablet goes and read new fresh data and plot it in a graph. Works like a charm.
(in case you'll be plotting charts, I used the AChartEngine and you can check on my profile a question/answer on it with some useful info)
the code below is a simplified version of what I'm doing. The complete version includes SEVERAL try{ } catch() { } in case it catches an exception it try closing the socket and return null;
public static String SendMessage(String message, String ip, int port) {
// Connect to host ==================================
Socket socket = new Socket();
socket.setSoTimeout(TIMEOUT);
InetSocketAddress addr = new InetSocketAddress(ip, port);
socket.connect(addr, TIMEOUT);
// Send Message ======================================
byte[] outputBuffer = message.getBytes();
socket.getOutputStream().write(outputBuffer);
// Zero the input buffer =============================
for (int i = 0; i < inputBuffer.length; i++) {
inputBuffer[i] = 0;
}
// Read the response ==================================
int count = 0;
do {
count = socket.getInputStream().read(inputBuffer);
} while (count != -1);
// Close connection ====================================
close(socket);
// Return message ======================================
return new String(inputBuffer).trim();
}
hope it helps,
happy coding.
1. Socket will be a good idea.
For Sending :
Socket s = new Socket();
s.connect(new InetSocketAddress("IP_ADDR",PORT_NO);
OutputStream o = s.getOutputStream();
PrintWriter pw = new PrintWriter(o);
pw.write(msg); // msg will be the data needed to send
For Receiving:
Socket s = new Socket();
s.connect(new InetSocketAddress("IP_ADDR",PORT_NO);
InputStream i = s.getInputStream();
InputStreamReader isr = new InputStreamReader(i);
BufferedReader br = new BufferedReader(isr);
String str = new String();
while((str=br.readLine())!=null){
System.out.println(str); // do whatever u want to do with str, the data read
}

Java - InputStream - Test for input

I am sending data to a server in two steps:
1) Length of what I will send using byte[4]
2) Data.
The server listens to the exact length of the data (shipped first) and then replies.
So I listen to the InputStream and try to get the data.
My Problem:
Whatever I am doing I am getting only the stream I send, but the server definatly sends a new string.
It seems I cannot wait for a -1 (end of string), as the program would time out and I am sure the server does not send anything alike.
Therefore I am using inputStream.available() to find out how many bytes are left in the buffer.
Once I am sending inputStream.read() after reading all the data it will time out with "Network idle timeout".
But I need to listen to the inputStream to make sure I am not missing information.
Why am I only receiving the information I send and not what is send by the server?
How can I listen to the connection for new items coming in?
Here is my code:
private void sendData (byte[] sendBytes){
try {
os.write(sendBytes);
os.flush();
} catch (IOException ex) {
}
}
Please help
THD
This is how you normally read all data from a reader (until the other end closes):
//BufferedReader is
StringBuilder data = new StringBuilder();
char[] buffer = new char[1024 * 32];
int len = 0;
while ((len = is.read(buffer)) != -1) {
data.append(buffer, 0, len);
}
//data will on this line contain all code received from the server

Categories