Android socket stable communication - android

I am working on Android project which communicates over TCP/IP. Communication works on specific protocol - this protocol is message oriented.
android device sends message to server via socket
server sends answer message to android device
It is not problem but I have a few parlous questions.
I don't have any idea how to solve connection interrupts (wifi, edge, change wifi to edge over open socket, ...) and connection timeouts? If android device sends 1 message and in this moment are connection problems - then android device sends different message (other request) - it is guaranteed that answers will be delivered in correct sequence?
I tried set timeout for socket object but it didn't work. I dont know why but if I set timeout to 5 seconds and I turned off the server before I sent message - it took more than 5 second before she came exciption.
I didn't found any articles on internet about this problems.
Thank you very much.

For TCP sockets the way you can get timeouts is by using select() or poll(),in Android you have to use SocketChannel() (java.nio) class to deal with non-blocking sockets. They both can query a socket for a specific period (10 or 20 seconds for example) and can tell you if it is writeable (you can use send()) or readable (there is data to be read recv()). Also the select() command will tell you if the socket has an error, most probably a broken connection. When you get such an error (except an interrupted signal, this one should be ignored and reissue the select), all you can do is close the socket and reopen a new one with the server, there is no way, as far as I know, to recover a broken connection, although, if you've implemented in the protocol, you can resume where you left off when the socket was broken. I don't know how you've implemented the protocol, but most of them will required a positive ACK (acknowledge) from the receiver before going on with another message. Also, when establishing a connection the client should specified if it a brand new connection or a broken one and act accordingly.
The idea is:
The sender sends a header specifying the command to process and the length of the data it's going to send after the header, the receiver receives the header and the data, once it process it, it sends a response ACK packet to the sender with a positive value to acknowledge the message, optionally with some data in case it's necessary. If after a reasonable period of time you don't receive the ACK packet then you may resend the same data again until you receive the positive ACK.
There could be the situation where the client sends a message, the server receives it and processes it, but when the server sends the positive ACK packet the connections breaks and the client never receives the packet, so it will resend the same message again once the connections is reestablished. To avoid this situation, it's necessary to send a message ID (an int which increments for every message sent) in the header to identity it.
I know it sounds difficult and it's in fact. If the connection is on the same network (intranet) it works nicely but, when the communication is on the internet, you may face a lot of problems and situations which you can't control, so it's necessary a well defined protocol where you can recover from broken connections and the transactions/messages won't be duplicated.

Related

Asynchronously receive Datagram/TCP packet over Android Client Socket

As shown above, I have a socket server (in UDP) running on my Raspberry Pi. I also have a socket client running on my Android app.
Currently, the app client always initiates communication and the RasPi always responds.
The RasPi can even initiate communication and send socket packet to anyone if it knows the IP address.
The problem is my app has to wait for a Thread to receive data forever (basically polling). Like below:
uniSocket.receive(receivePacket);
Should both RasPi and Android run clients and servers or is there something like Datagram_Socket_Callback or some asynchronous method to receive and send data.
The receive call will block until there is something to receive. That isn't polling; it's just waiting. It could wait in the receive call for days at a time if there's no notification to be sent. And that occupies no more resources than a server threading running on the android side (waiting for a connection) would occupy.
You probably will need some kind of periodic keep-alive to ensure the other side hasn't disappeared. You can do that yourself at the application layer, or TCP provides a keep-alive mechanism you can activate with setsockopt for this purpose.
In other words, create a socket, enable TCP keep-alives, send an "I'm waiting for notifications" message to the server, and then call receive to wait. The server then maintains a list of client connections waiting for notifications, and can then send data through a connection whenever there is something to be sent.
For your normal client-server communications, you could use the same socket, but it might be more complicated to synchronize that way, so alternatively, you could just create another socket in parallel.
I don't know a lot about android/app development but obviously your client will need to be prepared to re-create the connection if it's broken. I can think of many reasons why that might happen in normal usage. For example, the initial connection might be created from an IP address obtained on your home network. Then you walk out of your house and lose that IP address. You may now need to recreate the connection with a different IP address on the cell network (or the wifi at the coffee shop or whatever). If the phone goes into Airplane mode, you might lose all IP addresses for a time.
I'm sure it's possible to create a server that runs in android as well, but then you have the problem of the RPi needing to know the android's IP address which may change frequently. I would say it's better to keep the client role on the android side.

Detecting online status of device and sending back to server

Hi I am developing android application in which I want show whether other person is online or not so that person can intiate the communication.I thought about few solution :
1) Implementing heartbeat mechanism, in which device will send ping request to server after fix interval of time.
2) Server will send push type ping to client and client will give response on that so that server will know that client is online.
First case causes battery and data issue, while second one causes delay in push which will affect the process.
Is there any better solution for this problem? Apart from these or improvise version of above one.
nilkash. Virtually any method for checking network connectivity will at the end result in sending periodical pings between device and the server. Even push type ping will actually do the same (but it saves battery because push notifications aggregate messages for all applications in-to a single connection to a google server). So the best solution is just a proper combination of optimizations and you have to choose them depending on your requests.
Server pushes are power efficient, mostly because they reuse the
same connection for all applications, but the delay can be huge,
something like 10 minutes.
You can subscribe to connectivity
events and send "online" message to server once you are online. (But
not once you are offline because you are... offline). This will give
you immediate online events.
Do not send pings from device when there is no connectivity. Your application should be absolutely idle so as not to use battery.
There is no easy way to find out
when client goes offline on server side. You have to trade
traffic/battery for time resolution. More often you send pings, the
better resolution is. But you can't change ping interval for pushes,
so if you need better resolution, then you need to use your own
connection. But you can send other useful data through that connection too.
If you keep a TCP connection, then your pings can be
very data efficient: TCP keep alive packets are just 60/54 bytes.
But then you have to keep open connections with all clients on the
server. This may be a problem if you have a lot of clients.
The best combination may be something like that: you always send online message from a client when it becomes online. You keep TCP connection while the application is in foreground. You use the same connection to transfer data to and from the application. When your application goes to background you fallback to power consuming push based pings and do them at 10 minutes basis.

Android - How to know if a TCP connection is still opened

I'm doing an application that will comunicate with a TCP server. I based my work on the following example http://myandroidsolutions.funcode.ro/2013/03/31/android-tcp-connection-enhanced/.
Right now I'm looking how to verify if there is a connection between Client and Server. The mBufferOut.checkError() only give an error after 2/3 tries. I need to know if my message was sent or not.
Thank you
In network communications, you are never sure when (or if) the remote party received the message in full, in part, or at all.
If the connection is broken, then you know for certain that message was not received in full.
But if you need a timely confirmation, the server should send some confirmation message. Your application protocol needs to support this, though.
The same is valid to know if the connection is "up" or "down": TCP does not exchange any packets when idle, unless you activate keep-alive (which is not normally recommended). It may well happen that the party thinks it has a connection, only to send a message and then it fails (perhaps because a router was reset while the connection was idle).
To solve the problem we need to look at the return value of readLine(). If it return null so our tcp connection was closed.

Android client tell Syn & receive Rst Ack

I'm working for an App Android and I need my phone was always connected to my server MQTT...
But my phone can lost his connection(Tel :[FIN;ACK]; Serv:[FIN;ACK];Tel:[ACK]); after that, when he send a [SYN] message for connect it to the server MQTT, the serveur send an [RST,ACK]... And this while the service of my app is in activity.
In my case , i MUST to re-launch my server if i want my phone can be reconnect, but, i can't reboot my server (multi-phone possible, and i need real-time performence).
There is there a possibility to connect my phone without reboot my server?
Thank's for time.
Best regard
Guillaume
I think your problem is similar to the one I had. The connection was half closed. See http://www.codeproject.com/Articles/37490/Detection-of-Half-Open-Dropped-TCP-IP-Socket-Conne for details.
The way I solved this was to i) add keep alive msgs, every 5 secs. from the phone to the server and ii) have the server close the connection if there was no incomming data for 15sec. See http://www.forward.com.au/pfod/CheapWifiShield/index.html and www.pfod.com.au
MQTT includes keepAlives (PING request msgs) so you only need to modify your client to specify a short keepAlive interval
see http://www.hivemq.com/blog/mqtt-essentials-part-10-alive-client-take-over
to have the MQTT server to more quickly close the connection once it stops getting your data or keepAlive msgs.
Although the above link states
"The broker will close the previous connection to the same client (determined by the same client identifier) and establishes the connection with the newly connected client. This behavior makes sure that half-open connection won’t stand in the way of a new connection establishment of the same client."
So you should not be having this problem at all !!!

Maintaining a bidirectional UDP connection

I'm writing an Android UDP client that connects to and communicates bidirectionally (with no relationship between sent and received messages) with a Windows server. Once the initial Datagram has been sent to the server I want to be able to send data in either direction at any time. My questions are:
1) Is it correct to keep the initial socket open and use it for both sending and receiving ?
2) Should I send and receive in the same thread (with a timeout on receive) or in separate threads (allowing the receive to block) ?
3) Will the socket automatically close if data is not sent / received within a certain interval ?
Yes, that is no problem and is the most convenient way to deal with the bidirectional communication. Also, if the client is placed behind a NAT, it is required for the hole punching to work correctly. Even though you bind to the same IP and port on the client, you are not guaranteed to get the same mapping in the NAT. Thus, the server might not be able to reach the client. Remember that these mappings time out and are initiated from inside the NAT'ed network, so some probing might be needed if the client is idle for a long time.
That is up to how you design the application, but there is no problem doing so. Just monitor both the read and write status of the socket using for example select. If you create a non-blocking socket combined with a read/write-queue, you are sure never to block operation. As UDP either writes everything or nothing, the queue's are quite straight-forward.
Based on my experience, that is vendor-specific on Android. Some phones keep sockets open for a long time, while others close them after a certain idle-period. All phones seem to close sockets when the device goes to sleep (the state when the power button is pressed), except those associated with a background task.

Categories

Resources