I'm receiving real-time data from HC-05, just numbers from 0 to 1023.
SleepDuration variable is for the sleep duration between getting data from HC-05 and it can be chosen by the user between 1sec to 2 seconds, and this is the problem :
When the user chooses 1 second for SleepDuration, the program works fine but when he chooses over 1 second, this thread sleeps forever after getting few data.
This is my code for receiving data :
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
// Read from the InputStream
try {
bytes = mmInStream.read(buffer);
incomingMessage = new String(buffer, 0, bytes);
try {
sleep(SleepDuration);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage());
break;
}
}
}
This can happen if you are blocked into the instruction mmInStream.read(buffer)
Basically when you call the read, you are blocking the client waiting for some data, if data does not come your code blocks in the read forever.
Related
I'm trying to implement a communication system with an automatic repeat request strategy. I use three classes: Transmitter, Channel, Receiver. I have a maximum number of byte for message (window). But when I receive the byte sent, sometimes I receive less bytes than window. Why?
My code is this:
Transmitter
int n = 0;
int remaining, length;
while (n<channelBytes.length) {
remaining = channelBytes.length-n;
length = (remaining<window)? remaining : window;
outputStream.write(channelBytes,n,length);
// wait for the ack
byte[] b = new byte[4];
channel.socket().setSoTimeout(2000);
inputStream.read(b);
n += ByteBuffer.wrap(b).getInt();
}
Channel
bytes = new byte[SystemModel.WINDOW];
while(true) {
// receive from Tx
upInputStream.read(bytes);
// insert channel error
insertError(bytes);
Thread.sleep(propagationDelay + transmissionDelay);
// send bytes to Rx
downOutputStream.write(bytes);
// wait for the ack from Rx
clientChannelDown.socket().setSoTimeout(2000);
byte[] ack = new byte[4];
downInputStream.read(ack);
// send ack to Tx
upOutputStream.write(ByteBuffer.allocate(4).put(ack).array());
}
Receiver
byte[] b = new byte[SystemModel.WINDOW];
while (true) {
try {
int received = inputStream.read(b);
channelCoding.decodePartially(b);
}catch (SocketTimeoutException te){
break;
} catch (IOException e) {
e.printStackTrace();
} catch (DataFormatException e) {
// send ack
int ack = Integer.parseInt(e.getMessage());
try {
outputStream.write(ByteBuffer.allocate(4).putInt(ack).array());
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
In the Receiver, the array of bytes "b" is not always the length of the window.
Invalid code. See the Javadoc. InputStream.read(byte[] [,...]) isn't obliged to transfer more than one byte, and it is never valid to call it without storing the result into a variable. If you're expecting more than one byte, you have to loop, or use DataInputStream.readFully().
The canonical way to copy streams in Java is as follows:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
For ByteBuffers with Channels it is as follows:
while (in.read(buffer) > 0 || buffer.position() > 0)
{
buffer.flip();
out.write(buffer);
buffer.compact();
}
If you code correctly there is no need to insert sleeps into network code.
E&OE
I'm trying to write a program which acts as a server that will read bytes from a client that is written in PHP - sends request via socket (which i cannot recode due to policy) Here is the server code:
The server runs in: Red Hat Enterprise Linux Server release 6.2 (Santiago)
public void run() {
try {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(0);
while(!isInterrupted) {
try {
Socket server = serverSocket.accept();
LOG.info("Request received from : " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
// DataInputStream in = new DataInputStream(
// new BufferedInputStream(server.getInputStream(), 10000));
byte[] bytes = new byte[10000];
int byteDupLength = in.read(t_bytes);
// in.readFully(bytes); // I tried this but to no avail
// int byteDupLength = bytes.length;
LOG.info(byteDupLength);
byte[] byteDup = new byte[byteDupLength];
System.arraycopy(bytes, 4, byteDup, 0, byteDupLength);
// FOR INFORMATION ONLY
/*for (byte b : byteDup){
LOG.info(b);
}*/
ByteBuffer buffer = ByteBuffer.wrap(byteDup);
LOG.info(buffer);
forwardRequest(byteDup);
server.close();
}
catch(SocketTimeoutException s) {
LOG.error("Socket timed out!", s);
break;
}
catch(IOException e)
{
LOG.error("IOException:", e);
break;
}
}
}
catch (IOException ex) {
LOG.error("Server socket is null", ex);
}
LOG.fatal("ReceiverEngine interrupted!");
}
I encountered a problem when the client sends request consisting of 4948 bytes. The only bytes the server can read is 2090.
Another thing that seems a mystery to me is that, when I run the server via Netbeans in my local (which is a Windows 7 Pro), it works as expected. I dont know what is wrong. Please help.. :)
Thanks!
TCP is a byte stream protocol.
The read() method isn't guaranteed to fill the buffer.
Therefore if you don't receive the expected number of bytes in a single read, you have to loop until you do receive them.
readFully() would have worked if the buffer size agreed with the size of what was sent. In your case you specified a buffer of 10,000 bytes, which weren't sent, so it would have blocked waiting for the other 10000-4948 bytes.
I'm struggling here...
I'm trying to determine if data was successfully sent to the server through a TCP socket using the OutputStream object. For testing on emulator socket communications is loss after 30 sec. For write data OutputStream.write(); its doesn't throw an exception , and local server continuously running its not crashing, only tcp socket connection is loss after some time. All the methods in the socket class return as though the socket is active and working. Is there anything I'm doing wrong here? Is there any socket implementation or stream implementation I can use to get an exception or error when the stream/ socket doesn't actually send the data in the buffer? Also setting setSoTimeout() on the socket doesn't seem to do anything.
Please guide me...
Here is my code:
private void sendRec() {
int lstream;
int port = 1012;
byte[] byterecv = new byte[1040];
while (true) {
System.out.println("POOL-2");
synchronized (recSendThread) {
try {
recSendThread.wait(20);
} catch (InterruptedException e) {
}
}
if (stopcall == true) {
// break;
}
try {
// Provides a client-side TCP socket
Socket clientRec = new Socket();
// serverSocket = new ServerSocket(port);
// serverSocket.setSoTimeout(5000);
// Connects this socket to the given remote host address and
// port
clientRec.connect(new InetSocketAddress("192.168.1.36", port));
System.out.println("Just connected to "
+ clientRec.getRemoteSocketAddress());
System.out.println("SENTS Rec BEFORE");
// output streams that write data to the network
OutputStream outToServerRec = clientRec.getOutputStream();
DataOutputStream outStreamRec = new DataOutputStream(
outToServerRec);
outStreamRec.write(bData);
System.out.println("SENTS Rec AFTER");
// input streams that read data from network
InputStream inFromServerRec = clientRec.getInputStream();
// clientRec.setSoTimeout(5000);
DataInputStream inStreamRec = new DataInputStream(
inFromServerRec);
while ((lstream = inStreamRec.read(byterecv)) != -1) {
System.out.println("startrec bytearray -- "
+ byterecv.length);
bos1.write(byterecv, 0, lstream);
}
inStreamRec.close();// for closing dataouputstream
clientRec.close();// for closing socket connection
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is my receiver and player code..
/**
* start receiving the voice data from server
* */
protected void startplay() {
System.arraycopy(frndid, 0, playByteData, 0, 4);
System.arraycopy(userid, 0, playByteData, 4, 4);
ByteBuffer.wrap(sessionid).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().
put(call_sessionid);
System.arraycopy(sessionid, 0, playByteData, 8, 4);
int lstream;
int port = 1014;
while (true) {
System.out.println("POOL-3");
try {
if (stopcall == true) {
System.out.println("BREAKEDDDD1111");
//break;
}
// Host name
// port++;
InetAddress addressPlay = InetAddress.getByName("192.168.1.36");
// Creates a new streaming socket connected to the target host
Socket clientPlay = new Socket(addressPlay, port);
System.out.println("Just connected to play : " +
clientPlay.getRemoteSocketAddress());
System.out.println("SENTS Play BEFORE");
// output streams that write data
OutputStream outToServer = clientPlay.getOutputStream();
DataOutputStream outStreamPlay = new DataOutputStream(outToServer);
outStreamPlay.write(playByteData);
System.out.println("SENTS Play after");
// input streams that read data
InputStream inFromServerPlay = clientPlay.getInputStream();
DataInputStream inStreamPlay = new DataInputStream(inFromServerPlay);
//clientPlay.setSoTimeout(5000);
while ((lstream = inStreamPlay.read(byteArray)) != -1) {
System.out.println("startplay() bytearray -- " +
byteArray.length);
bos.write(byteArray, 0, lstream);
}
inStreamPlay.close();
clientPlay.close();// for closing play socket connection
responseBuffer = bos.toByteArray();
System.out.println("BAOSSIZE " + bos.size());
bos.reset();
bos.flush();
bos.close();
playing = true;
System.out.println("res length -- " + responseBuffer.length);
rcvbb=ByteBuffer.wrap(responseBuffer).order(ByteOrder.LITTLE_ENDIAN).
asShortBuffer().get(playShortData);
playVoiceReceived();// plays received data
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* start playing received the voice data from server
* */
public void playVoiceReceived() {
System.out.println("POOL-4");
try {
if (at != null) {
if (at.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
at.play();// starts playing
} else {
System.out.println("Play BEFORE WRITE");
// Writes the audio data to the audio hardware for playback.
at.write(playShortData, 0, BufferElements2Play);
System.out.println("Play AFTER WRITE");
at.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
The socket has sent the data ... to the local socket send buffer. What happens after that is up to the local TCP stack, the network, the remote TCP stack, and the remote application. If you want to know whether the remote application got the data, it will have to send you a reply.
Operator write does not check whether data was delivered because otherwise it would have to wait for too long time. If network connection is actually down, TCP layer of operating system, will try to send data anyway, but will detect problems somewhat later, i.e. 1 minute later, because it will not receive acknowledgement messages from the opposite side. It will then try to resend data several times, see that problem persists and only then will report exception condition on the socket. To know that socket is in exception condition, you need to perform some operator on socket, i.e. another write attempt. Try doing write in a loop like this:
while (true)
{
outStreamRec.write (data);
Thread.sleep (1000L);
}
It should throw an error about 2 minutes after network will be down.
Note, that in opposite to write operation, operation connect is synchronous, so it actually waits for response from the opposite side, and if there is not respose, it will throw an exception.
I am using bluetooth chat in order to connect and recieve data from a bluetooth device.
I use the following code for reading data:
public void run() {
byte[] buffer = new byte[1024];
int bytes;
Log.v("MR", "start listening....");
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
Log.d("MR", "buffer in try");
bytes = mmInStream.read(buffer);
Log.d("MR", "input stream :"+(new String(buffer)));
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(Conn.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
Log.d("MR", "buffer after");
} catch (Exception e) {
Log.e("MR", "Error :"+e.getMessage());
//
connectionLost();
// break;
}
Log.d("MR", "buffer after while");
}
}
The device is sending data all the time without stopping.
With the above code I get the message of:
Log.d("MR", "buffer in try");
then it goes to the next line:
bytes=mmInStream.read(buffer);
and never returns from that call. I guess this is because it starts reading data from the device and doesn't stop until it disconnects. How can I read a certain amount of bytes at a time?
EDIT
Unless it stay to the bytes = mmInStream.read(buffer); code due to that it don;t get any data back on from the device?
I use DataInputStreams instead as you can do a readFully() method which waits to read a certain number of bytes before returning. I setup the BT connection like this:
BluetoothDevice btDevice = bta.getRemoteDevice(macAddress);
BluetoothSocket btSocket = InsecureBluetooth.createRfcommSocketToServiceRecord(
btDevice, UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"), false);
btSocket.connect();
InputStream input = btSocket.getInputStream();
DataInputStream dinput = new DataInputStream(input);
then later on when I want to read I use readFully:
dinput.readFully(byteArray, 0, byteArray.length);
My JAVA application sends a command to server (command=filename.ini). When the server receives this command it sends filename.ini contents through Socket.
The first problem I had was receiving only partial contents of the file. That happened when in the code I used while(in.available()!=0){//write bytes} because in.available() does not know how big/long the content of the file is. If I use while((numBytesRead = dis.read(buffer)) != -1){//write bytes} the loop will never terminate since the Socket connection remains always open. My question is how else can I terminate the loop once every byte has been received? Please help me I have tried everything. I understand where the mistake is but I don't know how to fix it.
The following is the part of the code I have at the moment:
public class TCPClient {
protected Socket s = null;
public DataInputStream in = null;
public TCPClient(InetAddress ipa, int port) {
Socket s1 = null;
try { //Open the socket.
s1 = new Socket(ipa.getHostAddress(), port);
} catch (IOException ex) {
System.out.println("Error opening socket!");
return;
}
s = s1;
try { //Create an input stream.
in = new DataInputStream(new BufferedInputStream(s.getInputStream()));
} catch (Exception ex) {
System.out.println("Error creating input stream!");
}
}
public synchronized byte[] receive() {
byte[] buffer = new byte[0];
ByteArrayOutputStream getBytes = new ByteArrayOutputStream();
try {
while (in.available() == 0) {
} //Wait for data.
} catch (IOException ex) {
}
try {
int numBytesRead;
buffer = new byte[1024];
while ((numBytesRead = dis.read(buffer, 0, 1024)) != -1) { //LOOP NEVER ENDS HERE BECAUSE CONNECTION IS ALWAYS OPEN
getBytes.write(buffer, 0, numBytesRead);
}
} catch (IOException ex) {
}
return (getBytes.toByteArray());
}
}
You need to define a micro protocol to say the receiver how long is the file, or just close the connection on the server after finishing sending the file. First method is preferred, since it is a little bit more robust. On the client you should have a timeout too in order to avoid to wait forever in case of network problems.
Clarification for micro protocol: before sending the file itself send a 32 (or 64 if needed) bit integer containing the file length. The client should read that integer and then start retrieving the file.