Android client socket doesn't send data after some time - android

I'm developing an Android real-time-data app that sends data (floats and ints) to a server on the local subnet via a TCP socket. The problem I'm facing is that after sending some data simultaneously the socket doesn't send anymore data at all. I debugged the app and it shows that data is being sent but doesn't show up on the server. After this happens if I close the connection the server doesn't even get the notification that the connection has been terminated which it should according to my design model. Meanwhile I get an exception on the app saying it can not write to a broken pipe. This tells me that the problem is with the app because I also did test using a desktop app and I can send huge amounts of data to the server and it gets delivered.
And please keep in mind that the data size I'm talking about here is 252 bytes per packet.
Here's my class I'm using. (This runs in an AsyncTask object )
public class Network
{
private Socket handle;
public static enum TASK
{
TASK_CONNECT, TASK_SEND, TASK_CLOSE
}
public Network()
{
}
public String lastError = "";
public boolean Connect(String host, int port)
{
try
{
lastError = "Connecting to server.";
handle = new Socket(host, port);
handle.setTcpNoDelay(true); //
handle.setSendBufferSize(SIZE_OF_PACKET); ///==> These don't seem to help at all
handle.setKeepAlive(true); ///
return true;
}catch(IOException e)
{
lastError += e.getMessage() != null ? " "+ e.getMessage() : "";
return false;
}
}
private void err(String e){
System.err.println(e);
}
private boolean SendPacket(byte buffer[])
{
OutputStream oStream = null;
err("sending: " + buffer.length + " bytes");
try
{
lastError = "Obtaining output stream.";
oStream = handle.getOutputStream();
lastError = "Error sending data.";
oStream.write(buffer);
oStream.flush();
return true;
}catch(Exception e)
{
lastError += e.getMessage() != null ? " "+ e.getMessage() : "";
}
return false;
}
public void Close()
{
try{ handle.close(); handle = null; }catch(Exception e){} // swallow exception
}
}
I send my data in a loop depending on how many numbers I have. I tried a Google search but didn't find anything relevant. Has anyone experienced this before? It's making me mad now.
EDIT: Wireshark shows incoming "red" packets that don't reach the desktop app (server)
Look at this picture.
You can see the first few have Len > 0 the red ones have 0.
I think it's time Google interfaced the USB so we can use it. At least that'd would have been my first option.

Should you not be calling oStream.close() after you flush the stream, given that you never use it again?
Also, you say that this is being run in an AsyncTask object. Is it possible that multiple threads could be attempting to send packets at the same time? If so, you might need some form of synchronisation around the SendPacket method.

Ok. I solved the issue by using UDP instead. Thank you all.
But I still didn't find the source of the problem.

Related

Android connect to Bluetooth via Hands Free Protocol

I would like to create an application which can connect to a Bluetooth Headset via the Hands Free Protocol (HFP). I followed the Android example and have now a BluetoothSocket with its Input and OutputStream. Below you see my read and write methods (read method is executed by another Thread)
public void read() {
while (true) {
Log.d("ME", "Waiting for data");
try { // read until Exception is thrown
numBytes = inStream.read(dataBuffer);
String str = new String(dataBuffer,0,numBytes);
msgHandler.obtainMessage(numBytes, str).sendToTarget();
} catch (Exception e) {
Log.d("ME", "Input stream was disconnected", e);
break; // BluetoothDevice was disconnected => Exit
}
}
}
public void write(byte[] bytes) {
try {
outStream.write(bytes);
outStream.flush();
Log.e("ME", "Wrote: " + new String(bytes));
} catch (IOException e) {
Log.e("ME", "Error occurred when sending data", e);
}
}
When the connection is opened the Bluetooth headset sends AT+BRSF=191 over the InputStream. I tried to response with +BRSF:20\r but here is my problem. After that the device does not send any other data over the InputStream. It does not come to an Exception - it's more like the device does not know how to responde to my message. Do I send the wrong data? I have all the information from here: (HF = Hands-Free Unit AG = Audio Gateway)
Do you have any ideas what I did wrong? Have I missed something?
EDIT: These are my write calls:
write("+BRSF: 191\r");
write("OK\r");
You were missing the OK response. According to this document, the OK-code consists of a windows-style newline (CR LF), the literal OK and then another newline.
Do note that other commands are terminated by a carriage return only. For more information on the hands-free protocol, you can refer to that very document you linked in your post.
Example code:
public static final String OK = statusCode("OK")
public static final String ERROR = statusCode("ERROR")
public static String statusCode(String code) {
return "\r\n" + code + "\r\n";
}
public static String command(String cmd) {
return cmd + "\r";
}
Now you can use OK and ERROR in your code as constants, and you can use the statusCode method for other status codes.

Android Open Accessory USB communication failing after sending large data packets

I have an android phone communicating with a Linux machine using AOA. The Linux machine is set up to initiate the connection, then wait for incoming data and echo it back to the phone unchanged. This works fine for small packets of data (less than 1024 bytes) from the phone. However, if I send exactly 1024 bytes, it appears to work from the Android end, but the computer never sees the packet, just any following ones that are smaller. If the phone attempts to send packets larger than 1024, these do get received by the computer, but the android phone will no longer be able to receive any packets from the computer. Further confusing the issue, this did work in the past, yet rolling back to earlier versions of the transmitting/receiving code on the phone doesn't seem to have any effect. The code on the computer has not been changed.
The android app checks for a USB accessory at start-up, and if one is found it starts a listener and sender thread. The sender thread waits on a blocking queue for outgoing packets, and sends them as soon as they are received. The listener thread continuously attempts to read from the input stream, which blocks until data is available. This is the code I use for setting up & running the threads:
private boolean openUSB(){
mUSBManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mAccessory = mUSBManager.getAccessoryList();
if (mAccessory != null && mAccessory.length > 0) {
mParcelFileDescriptor = mUSBManager.openAccessory(mAccessory[0]);
mFileDescriptor = mParcelFileDescriptor.getFileDescriptor();
mListener = new Thread() {
public void run() {
listenerThread();
}
};
mListener.start();
mSender = new Thread() {
public void run() {
senderThread();
}
};
mSender.start();
displayText("Connected to USB accessory");
return true;
} else {
displayText("No USB accessory detected");
return false;
}
}
private void listenerThread(){
byte packet[] = new byte[SDR_PREFIX_SIZE+SDR_HEADER_SIZE+SDR_MAX_PAYLOAD+SDR_CRC_SIZE];
FileInputStream input = new FileInputStream(mFileDescriptor);
try {
ByteArrayOutputStream incoming = new ByteArrayOutputStream();
displayText("Listener Started");
while ( mFileDescriptor != null && input != null ) {
int read = input.read(packet,0,packet.length);
/* data in packet gets processed */
}
} catch ( Exception e) {
displayText("Listener Exception - "+e.getMessage(),true);
}
displayText("Listener Exited");
}
private void senderThread(){
displayText("sender started");
FileOutputStream output=new FileOutputStream(mFileDescriptor);
try {
byte data[] = mTransmitQueue.take();
while (data != null) {
displayText("Sending packet " + packet + ", "+data.length + " bytes");
output.write(data);
data = mTransmitQueue.take();
}
} catch ( Exception e) {
displayText("Sender Exception - "+e.getMessage(),true);
}
}
In the past, I had issues getting the listener and sender to work, until I found out that some of the intermediate objects that were used to create the file streams were being garbage-collected, yet were still needed. I now store all those intermediate objects to member variables (mUSBManager, mAccessory, mParcelFileDescriptor, mFileDescriptor) to give them persistence. I suspect that this issue is something similar, but I haven't been able to make any headway. I have been beating my head on this issue without any success, and really hope that others will have some insight on what is causing this.
I've found a work-around, expanding the buffer used for receiving data seems to fix the issue, even though the existing buffer was large enough for all packets. Increasing the buffer from 1524 to 2524 fixed the issue with incoming packets not being received. This is a kludgy solution, but it works.

QTcpServer with android client unable to print or use data received from client

I am developing Client-Server application in C++ using Qt framework, but the clients can be android phones and computers(Qt client app)
Now i'm having troubles to handle Reception of data on the server side; the server is not receiving data properly.
First, I got things working nicely between the server(Qt app) and the client(Qt app) using these methods for sending and receiving:
The size of the message is kept at the beginning of the packet to help check whether the whole message is received or not.
This is the method to send message to the clients
void Server::send(const QString &message)
{
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
out << (quint16) 0; // just put 0 at the head of the paquet to reserve place to put the size of the message
out << message; // adding the message
out.device()->seek(0); // coming back to the head of the paquet
out << (quint16) (paquet.size() - sizeof(quint16)); // replace the 0 value by the real size
clientSocket->write(paquet); //sending...
}
This slot is called every time a single paquet is received.
void Server::dataReceived()
{
forever
{
// 1 : a packet has arrived from any client
// getting the socket of that client (recherche du QTcpSocket du client)
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
if (socket == 0)
return;
QDataStream in(socket);
if (dataSize == 0) // if we don't know the size of data we are suppose to receive...
{
if (socket->bytesAvailable() < (int)sizeof(quint16)) // we haven't yet receive the size of the data completly then return...
return;
in >> dataSize; // now we know the amount of data we should get
}
if (socket->bytesAvailable() < dataSize)
return;
// Here we are sure we got the whole data then we can startreadind
QString message;
in >> message;
//Processing....
dataSize = 0; // re-initialize for the coming data
}
}
This is working well when the server is talking with the Qt app Client, because the same methods are used there, and the size of quint16 will remain the same hover it doesn't work with android client, then i tried another way in which i wanted to ignore the size of the message sent, but format the message in a way such that i can know where it starts and where it ends, then with some controls i can get it however i'm stuck here, cause the data read doesn't contain anything when printed, but his size has a value(which even vary according to the amount of text the client send)!
void Server::dataReceived() // a packet is received!
{
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
if (socket == 0)
return;
QByteArray data= socket->readAll(); //reading all data available
QString message(data)
qDebug() << data; // this prints nothing!
qDebug() << data.size();// But this prints a non null number, wich means we got something, and that number varies according to the amount of text sent!
qDebug() << message; // this also prints notghing!
}
PS: it's not working even for the Qt app Client.
Can you help me find out what's wrong, i'm a bit confused how the tcp protocol is handling the data, and if you could and also advise me a good way for doing this.
here is the android class I made for the purpose
class QTcpSocket implements Runnable {
private String ip="";
private int port;
private Socket socket;
private PrintWriter printWriter;
private DataOutputStream dataOutputStream;
private DataInputStream dataInputStream;
public QTcpSocket(String ip, int port) {
this.ip = ip;
this.port = port;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getIp() {
return this.ip;
}
public void setPort(int port) {
this.port = port;
}
public void run() {
try {
socket = new Socket(this.ip, this.port);
dataOutputStream = new DataOutputStream( socket.getOutputStream() );
dataInputStream = new DataInputStream(socket.getInputStream());
String response = dataInputStream.readUTF();
dataOutputStream.writeUTF("Hello server!");
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String message) {
try {
dataOutputStream.writeUTF(message);
}catch (IOException e) {
e.printStackTrace();
}
}
public void disconnect() {
try {
printWriter.flush();
printWriter.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean isClosed() {
return socket.isClosed();
}
}
Replace in 'data' all bytes with value 0 by value 20 and print again. I think you see nothing printed because the first byte is 0. You could also replace with 'X'. Did you already replace writeUTF() by write() ?
20 is the space character. But then you also see nothing printed so better use a X char. Strings get printed until a \0 char (which indicates the end of a string) is met. Because nothing was printed i supposed one right at the beginning. So writeUTF causes that leading 0. I could only explain that if all chars had doubled. What was the first char you sent?
But now: send size-of-message first so it equals your qt client.

Reconnecting to an Android Socket in order to wait for Server

So I have TCP server in Windows that is programmed in C++ and a client in JAVA, Android 4.0.4.
In Android, I connect like this:
public boolean sendConnectRequest()
{
while (isSocketConnected == false)
{
try {
if(comSocket == null)
comSocket = new Socket("192.168.0.1",1531);
isSocketConnected = comSocket.isConnected();
if (isSocketConnected) {
out = comSocket.getOutputStream();
in = comSocket.getInputStream();
}
else
comSocket.close();
}
catch (IOException ex)
{
Log.e("TCP Error", ex.getLocalizedMessage());
}
}
return true;
}
I typically have no problems with this code on the first connection to the server.
When i disconnect from the server, I call this:
public void closeConnection() {
if (comSocket != null)
{
try {
comSocket.close();
isSocketConnected = false;
if (out != null)
out.close();
if (in != null)
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
So here is the problem... I hit the home button on the smartphone, which places the program in pause. I start the program again and it calls the resume function in activity, which in turn starts the process toward reconnection. The connection is attempted and i get no errors. However, my Windows server records no connection. In Windows, I know that I am still blocked at:
SOCKET connectionSocket = accept(tcpNetworkData->socket, (struct sockaddr*)&from, &fromlen);
I believe this is normal. When I am in debug mode on the Android side, I notice that it returns immediately from the line: comSocket = new Socket("192.168.0.1",1531); This should indicate to me that a connection is made.
If you follow me so far... I should also say that if I shut the server down, the client resets by closing the connection and opening a new one. This time the comSocket = new Socket("192.168.0.1",1531) does not block as it should and the execution keeps going. This is obviously wrong. I think it is a resource release problem but why? With Winsock you can solve this problem with this line of code:
int so_reuseaddr = TRUE;
setsockopt(networkData->socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&so_reuseaddr,sizeof(so_reuseaddr));
Can you do something similar with Android or do you have to? Thank you for your help!
According to the javadoc the connection is established once you call the constructor.
Socket(InetAddress address, int port)
Creates a stream socket and connects it to the specified port number at the specified IP address.
When you press the home button, your app goes in background but it does not get killed immediately, so your comSocket might be not null when you get back to your application. In that case you are not calling the constructor again, thus you are not reconnecting to the server. What you should do is
if(comSocket == null){
comSocket = new Socket("192.168.0.1",1531);
}else{
comSocket.connect(new InetSocketAddress("192.168.0.1",1531));
}
(and please please place the curly brackets :-) )
Something to keep in mind is that the isConnected() method isn't very reliable for detecting when the remote side has closed the connection, (here is an example).
You have to figure this out by reading or writing on the associated Input/Output Streams.
Try using PrintWriter.checkError(), which will return true as soon as the client can no longer connect to the server.

Android asynctask reading from socket

Im having some trouble reading/writing to a tcp server for which im building an app. In a recent thread I was suggested to use a service instead but this is a project for school which suggested asyncTask so I might aswell go for that.
So the classes ive got are my activity class and async, nothing interesting is going on in activity but sending a string which is working so ill get on with the async one.
class ServerTask extends AsyncTask<Void, Void, Void>{
public static String ip = "10.0.2.2";
public static int port = 2002;
Socket socket;
public DataInputStream dis;
public DataOutputStream dos;
public String message;
#Override
protected Void doInBackground(Void... params) {
try {
socket = new Socket(ip, port);
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
} catch (Exception e) {
Log.i("AsyncTank", "Cannot create Socket");
}
while(socket.isConnected()){
read();
}
}
}
return null;
}
public void write(String message) {
try {
if (socket.isConnected()){
dos.writeUTF(message);
dos.flush();
} else {
Log.i("AsynkTask", "Socket appears to be closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "Writing failed");
}
}
public String read() {
try {
if (socket.isConnected()) {
message = dis.readLine();
} else {
Log.i("AsyncTask", "Cannot read");
}
} catch (Exception e) {
Log.i("AsyncTask", "Cannot read from stream");
}
return message;
}
}
Things I do know, the server DOES get the messages but it doesnt update until I restart the server which leads me to believe that im not pushing a new line or something which makes it all appear as one line after its closed. This however might aswell be the server for which im not reponsible so ill have to read up in that.
The read part however does not want to work, im not sure on how to call the method to have it constantly listen and react to the servers sockt? I tried make a thread just before the return in doInBackGround but then the application starts works for a couple of seconds the force closes due to lack of memory? Do I need a thread to keep constantly listen?
The whole point of this as you might guess is to make a chat so the read method is eventually supposed to update a textView in my activity class. The send method is "working" but not as it should though this might be as I said earlier the server doing some funky buisness.
Another one, is it even possible to have the read as a method like I have or does something have to react when the server sends data and then call the method?
Edit
I have now moved the read part, or atleast some of it to doInBackGround so its now
dis = new BufferedReader(new InputStreamReader(socket.getInputStream()));
message = dis.readLine();
Log.i("AsynkTask", "Read : "+message+" this is doInBackGround!");
This along with a change to simply hardcode a printline in the server made me read that line in the client so im guessing its working realtively good for now.
How is it looking? Is it utter crap this code and should be done some other way? Got my functionality but never bad to learn to do it better so to speak :).
You should do both your writing and reading to the Socket in an AsyncTask's doInBackground() method, as both take time and could block the main (UI) thread. I don't know how you are calling your write() method above but you might also want to take a look at this question that might be related.

Categories

Resources