Android Socket InputStream problem - java

I have a server written in VB, it sends data to clients in periods of 3 seconds. I've written a client Java code like this:
class Commu extends Thread {
Socket socket;
InputStream inputStream;
OutputStream outputStream;
public Commu() {
try {
socket=new Socket();
socket.connect(new InetSocketAddress("192.168.0.1", 1234)));
inputStream=socket.getInputStream();
outputStream=socket.getOutputStream();
this.start();
} catch(Exception e) {
System.out.println(e);
}
}
public void run() {
while(true) {
byte[] buffer=new byte[1024];
inputStream.read(buffer);
System.out.println(buffer[0]);
}
}
}
It works fine on my desktop, it prints message whenever the VB server sends message.
It works on Android, but the inputStream read only once, and then get stuck; If I want to read more data, I have to use outputStream to send some data, then inputStream will read once, and get stuck again. That is really strange, could anyone tell me why?
There is no problem in System.out.print(), because DDMS can show it, I promise! The problem is inputStream should not read only once, it should read when data comes. But it didn't , it read only once.
Even if, I only print one byte from the buffer, it get stuck on Android. It works very well on desktop, but get stuck on Android.

That's a wierd piece of code. You don't check the return value of read() for -1, i.e. EOS, and you only display the first byte of the data received and throw the rest away.

Related

I'm misunderstanding something on how to set up sockets, but I'm not suer if it's client side, server side, or both

I'm setting up a simple program to test starting a server, and I'm getting a silent failure state. My client seems to think it has sent, while my server doesn't think it's recieving. The two are managing the initial connection, it's just sending things after that where it's failing.
I've cut things down to the core of where it's currently failing I think.
Here's part of the Client code
public void Client (int port, String ip)
{
try {
sock = new Socket(ip, port);
System.out.println("Found the server.");
streamInput = new DataInputStream(sock.getInputStream());
// sends output to the socket
streamOutput = new DataOutputStream(
sock.getOutputStream());
streamOutput.writeChars("Client Begining Conversation");
System.out.println(streamInput.readUTF());
}
catch (UnknownHostException u) {
System.out.println(u);
return;
}
catch (IOException i) {
System.out.println(i);
return;
}
}
public static void main(String[] args) throws IOException {
// create the frame
try {
ClientGui main = new ClientGui();
main.Client(8000,"127.0.0.1");
main.show(true);
} catch (Exception e) {e.printStackTrace();}
Here's server code.
public Server(int port) throws Exception
{
ServerSocket gameServer = new ServerSocket(port);
Socket gameSocket = gameServer.accept();
System.out.println("Client has connected");
// to send data to the client
PrintStream dataOutput
= new PrintStream(gameSocket.getOutputStream());
// to read data coming from the client
BufferedReader reader = new BufferedReader( new InputStreamReader(
gameSocket.getInputStream()
));
//play logic
Play(reader,dataOutput);
public void Play(BufferedReader reader, PrintStream dataOutput) throws Exception
{
String received, textSent;
System.out.println("Waiting for response.");
received = reader.readLine();
System.out.println("Client has responded");
//contenue until 'Exit' is sent
while (received != "Exit" || received != "exit") {
System.out.println(received);
textSent = received + "recieved";
// send to client
dataOutput.println(textSent);
}
}
My client gets to here -
Found the server.
and my server gets to here -
Trying to start server.
Client has connected
Waiting for response.
At which point, it just hangs forever, each side waiting for the other. It doesn't throw an error, it just... waits until I force it closed.
So it appears that I'm either doing something wrong when I send with "streamOutput.writeChars" in my client, or I'm doing something wrong when I receive with my server with "reader.readLine();", but I can't figure out what.
Or I could be doing something more fundamentally wrong.
The problem is that reader.readLine() doesn’t return until it sees a new line character, but streamOutput.writeChars("Client Begining Conversation") doesn’t send one.
More generally, mixing a DataOutputStream on the client with a BufferedReader on the server won’t work reliably, as the latter expects plain text, while the former produces formatted binary data. For example, the character encoding might not match. The same applies to communication in the opposite direction with PrintStream and DataInputStream. It’s best to pick either a text based or binary protocol and then be consistent about the pair of classes used on both the client and server.
In the case of a text protocol, an explicit character encoding should be defined, as the default can vary between platforms. As a learning exercise, it might not matter, but it’s a good practice to be explicit about specifying a character encoding whenever handling networked communication. UTF-8 is a good choice unless there’s a specific reason to use another one.
In addition, it is generally preferred to use PrintWriter instead of PrintStream for text output in new code. Read this answer for an explanation.

Unresponsive socket read buffer

I am trying to send data to one of my servers and receive an ACK back from it. However, the processing gets hung up when waiting for a response from the server. I know for a fact that there is a connection because I can see the data reaching the server. I also know that the server is outputting data correctly because my C# client is receiving data back from the server. I will note that this client is running on a centOS virtual machine. The server is a remote windows machine. I wouldn't imagine that there would be an issue due to the virtual environment because I am able to use an SNMP java client (SNMP4j package) to make calls to a remote server. I believe my server is outputting raw binary too, but I would expect to see some kind of output either way.
// A Java program for a Client
import java.net.*;
import java.io.*;
public class Client
{
// initialize socket and input output streams
private Socket socket = null;
private DataInputStream input = null;
private DataOutputStream out = null;
private DataInputStream serveroutput= null;
// constructor to put ip address and port
public Client(String address, int port)
{
// establish a connection
try
{
socket = new Socket(address, port);
System.out.println("Connected");
// takes input from terminal
input = new DataInputStream(System.in);
// sends output to the socket
out = new DataOutputStream(socket.getOutputStream());
serveroutput = new DataInputStream(socket.getInputStream());
}
catch(UnknownHostException u)
{
System.out.println(u);
}
catch(IOException i)
{
System.out.println(i);
}
// string to read message from input
String line = "";
// keep reading until "Over" is input
while (!line.equals("Over"))
{
try
{
line = input.readLine();
out.writeUTF(line);
System.out.println(serveroutput.readLine())
}
catch(IOException i)
{
System.out.println(i);
}
}
// close the connection
try
{
input.close();
out.close();
socket.close();
}
catch(IOException i)
{
System.out.println(i);
}
}
Could be great if you would share the otherside codes. (sorry cannot comment yet)
Try use something else over writeUTF(), simply maybe a PrintStream, as mentioned by #marquis-of-lorne (read|write)UTF may be confusing by the peer.
Also this might be a good practice to flush() out the output from both side when there is nothing else to send to make sure data is sent completely.
You may also try BufferedReader over InputDataStream as you are trying to read lines. readLine() from InputDataStream is deprecated.

Java Socket read and write unexpected behavior

I faced an issue while transferring file from client to server. So I did a simple client and server code in java using sockets. I found some unexpected behavior. I can't find why it happens so. Following is the code
Server side code:
import java.io.*;
import java.net.*;
class Server
{
public static void main(String args[])
{
ServerSocket ser;
try {
ser=new ServerSocket(9000);
Socket cnfcon=ser.accept();
OutputStream outstr=cnfcon.getOutputStream();
InputStream inpstr=cnfcon.getInputStream();
PrintWriter out=new PrintWriter(outstr,true);
BufferedReader inp=new BufferedReader(new InputStreamReader(inpstr));
File f=new File("test.txt");
InputStream fis= new FileInputStream(f);
long size=f.length();
System.out.println("Start Server");
out.println(f.getName());
out.println(size);
byte[] buff1=new byte[]{0,1,2,3,4,5,6,7,8,9};
byte[] buff2=new byte[]{7,1,2,3,8,5,6,7,8,9};
outstr.write(buff1);
//inpstr.read(); -- tried including this and removing this
outstr.write(buff2);
//inpstr.read();
fis.close();
inp.close();
ser.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
client side code:
import java.io.*;
import java.net.*;
class test
{
public static void main(String args[]) throws UnknownHostException, IOException
{
Socket cnfcon=new Socket("127.0.0.1",9000);
OutputStream outstr=cnfcon.getOutputStream();
InputStream inpstr=cnfcon.getInputStream();
PrintWriter out=new PrintWriter(outstr,true);
BufferedReader inp=new BufferedReader(new InputStreamReader(inpstr));
File f=new File(inp.readLine()+"t"); //"t" - dummy
f.createNewFile();
FileOutputStream fos=new FileOutputStream(f);
int size=Integer.parseInt(inp.readLine());
byte buff[]=new byte[1024];
System.out.println("Start Client");
inpstr.read(buff, 0, 10);
disp(buff);
//outstr.write(1); -- tried including this and removing this
inpstr.read(buff, 0, 10);
disp(buff);
//outstr.write(1); 1 - dummy value
fos.close();
out.close();
cnfcon.close();
}
public static void disp(byte buff[])
{
for(int i=0;i<10;i++)
System.out.print(buff[i]);
System.out.println();
}
};
I am sending two buffers from server to client.
Here I expect first buffer should come first and next for next time.
But its unpredictable.
Some times it works as expected. Some times it gets the 2nd buff for both time. Some times all bytes in the buffer are zero.
I tried adding outstr.flush() before the message passing.
Is there any other way to implement this?
To be more clear, it seems client is not waiting for server to send or vice versa.
The output is different every time.
Suggestions are appreciated.
The problems are at least two:
You're ignoring the count returned by read(), and assuming it filled the buffer. It isn't obliged to do that. It isn't contracted to transfer more than one byte. You have to loop:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Data is disappearing into the buffered readers/writers/streams, and it is caused by using too many parts of the I/O stack. Don't use multiple readers, writers, and streams, on the same socket. Use a single output stream or writer and a single input stream or reader for the life of the socket. As you are writing binary data you shouldn't be using readers or writers at all.
Contrary to other answers here, it isn't necessary to add flushes or sleeps in this code, as long as you close everything correctly, or to fiddle around with available() results either.
Try adding a Thread.sleep() in the client when it receives the buffers? Not sure if it will work.
Let me guess , you are on Microsoft windows ?
First chunk your data into small chunks ( let's say 1kb ), but you are already doing that and then sleep a little bit in both your read and write loops. Call flush when possible after writes, and Be sure to make sure you don't read more than input stream.availible()
Your code should work on every other os without issue , without modification.

Java communication with TCP socket and PIC stuck in read()

I try to communicate with a java application to a µController in wifi (Flyport).
I have a problem with the java application :
It first create a socket to communicate with the Flyport server, then send a message and receive the Flyport answer.
Everything work fine until the read part. I'm polling the read() function of the BufferedReader until it return -1, but it doesn't. The first read works fine, all the answer are red, but the application stay stuck when it tries to read again.
My code is very simple :
Java application :
try (
Socket clientSocket = new Socket(hostName, portNumber);
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
)
{
...//Connection and sending message works fine
}
char[] buffer = new char[500];
while ((in.read(buffer)) != -1) { // first read() works fine, second read() stay stuck...
System.out.println(buffer); // display all answer sent by flyport
}
The code in the flyport :
while(isClientConnected){
//check if client is still connected
...
//read client message
while((RxLen=TCPRxLen(sock))>0)
{
TCPRead(sock,bff,RxLen);
strcat(msg,bff);
}
//write back to the client that the order is received
TCPWrite(sock, msg, strlen(msg));
//process the client order
...
//Write to the client that the process is done
TCPWrite(sock, msg2, strlen(msg2));
}
The java application read msg and msg2 with the first read(). msg and msg2 have "\r\n" at the end.
Doesn't somebody can tell me where I am wrong ?
Is there a function from BufferedReading that tells how much data there is left to read ?
Thanks and regards.
NB : I try with a small buffer in the java application, the problem is the same, read() is stuck when there is nothing left to read...
You're reading from the socket until end of stream, and you're never causing end of stream, as you are never closing the socket at the sender. Either close the socket or don't read until end of stream.

TCP detect disconnected server from client

I'm writing a simple TCP client/server program pair in Java, and the server must disconnect if the client hasn't sent anything in 10 seconds. socket.setSoTimeout() gets me that, and the server disconnects just fine. The problem is - how can I get the client to determine if the server is closed? Currently I'm using DataOutputStream for writing to the server, and some answers here on SO suggest that writing to a closed socket will throw an IOException, but that doesn't happen.
What kind of writer object should I use to send arbitrary byte blocks to the server, that would throw an exception or otherwise indicate that the connection has been closed remotely?
Edit: here's the client code. This is a test function that reads one file from the file system and sends it to the server. It sends it in chunks, and pauses for some time between each chunk.
public static void sendFileWithTimeout(String file, String address, int dataPacketSize, int timeout) {
Socket connectionToServer = null;
DataOutputStream outStream = null;
FileInputStream inStream = null;
try {
connectionToServer = new Socket(address, 2233);
outStream = new DataOutputStream(connectionToServer.getOutputStream());
Path fileObject = Paths.get(file);
outStream.writeUTF(fileObject.getFileName().toString());
byte[] data = new byte[dataPacketSize];
inStream = new FileInputStream(fileObject.toFile());
boolean fileFinished = false;
while (!fileFinished) {
int bytesRead = inStream.read(data);
if (bytesRead == -1) {
fileFinished = true;
} else {
outStream.write(data, 0, bytesRead);
System.out.println("Thread " + Thread.currentThread().getName() + " wrote " + bytesRead + " bytes.");
Thread.sleep(timeout);
}
}
} catch (IOException | InterruptedException e) {
System.out.println("Something something.");
throw new RuntimeException("Problem sending data to server.", e);
} finally {
TCPUtil.silentCloseObject(inStream);
TCPUtil.silentCloseObject(outStream);
TCPUtil.silentCloseObject(connectionToServer);
}
}
I'd expect the outStream.write to throw an IOException when it tries to write to a closed server, but nothing.
I'd expect the outStream.write to throw an IOException when it tries to write to a closed server, but nothing.
It won't do that the first time, because of the socket send buffer. If you keep writing, it will eventually throw an IOException: 'connection reset'. If you don't have data to get to that point, you will never find out that the peer has closed.
I think you need to flush and close your stream after written like outStream.flush(); outStream.close(); inStream.close();
Remember ServerSocket.setSoTimeout() is different from client's function with same name.
For server, this function only throws SocketTimeoutException for you to catch it if timeout is expired, but the server socket still remains.
For client, setSoTimeout() relates to 'read timeout' for stream reading.
In your case, you must show your server code of closing the connected socket after catching SocketTimeoutException => ensure server closed the associated socket with a specified client. If done, at client side, your code line:
throw new RuntimeException("Problem sending data to server.", e);
will be called.
[Update]
I noticed that you stated to set timeout for the accepted socket at server side to 10 secs (=10,000 milliseconds); for that period, did your client complete all the file sending? if it did, never the exception occurs.
[Suggest]
for probing, just comment out your code of reading file content to send to server, and try replacing with several lines of writing to output stream:
outStream.writeUTF("ONE");
outStream.writeUTF("TWO");
outStream.writeUTF("TREE");
Then you can come to the conclusion.

Categories

Resources