Maintaining a bidirectional UDP connection - android

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.

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.

Which is better between an android app and a server? Socket or timer?

I'm going to make an android app that needs to work like an instant messaging (Chat) application, but a little different. It needs to send and receive some short messages, and it's important that it delivers the messages from a web server to the android client quickly (that's a synchronizing app).
Also, the internet connection may be unstable (like GPRS). The server application uses .net 4.5 (may be a windows service or web service)
I've searched around but the answers were not clear for my questions. My questions are as follows:
Is it better to use an open socket or check the server every few seconds? (max allowed delay is 15-20 seconds)
How much network traffic does a socket use in a day, if it is open and no message passes?
How many sockets can be open at the same time?
It really depends on what you want to do, but here are some answers :
Reopening a TCP connection every few seconds probably won't hurt. Close+reopen is how most HTTP connections work.
An idle TCP socket doesn't send any traffic at all, unless you enable TCP keepalive, but even then it is still very light (and often adjustable).
Usually a lot, but is really depends on your software and hardware. A desktop computer may have 1000 open connections on normal load (but can certainly handle more). A big server may handle millions open connections.
Depending on what your 'synchronizing' thing is, you should consider synchronizing with GPS time. It is present on most mobile devices and have a precision around nanoseconds (= all devices will have the same GPS time, give or take some ns). But then the server may need GPS time too, depending on what you do.
Also depending on your application, you should consider using UDP sockets. The good points are that you only need one UDP server socket to handle ALL the UDP clients (you can't do lighter), and that it is more reliable time-wise (when there is a problem, TCP may re-transmit with high delay, while UDP is all or nothing, = you handle up-to-date re-transmit yourself). The downsides are that it is unreliable (messages can be dropped or corrupted, therefore you may want to add some safety), and that some ISP may restrict UDP more than TCP (test yourself to be sure, but usually there is no problems). Note that with UDP, you may need to 'keep alive' yourself, by sending a dummy message, but it is only needed if the 'connection' is idle for too long.

Use of TCP for real time small packet data over a period of time

I am pretty new to TCP networking and would like to use TCP for real time transfer of data.
Essentially, I need my PC python to send data (single character) to Android application. Data to be send changes in real time, and upon change to data (usually about 0.5 - 1sec apart), it has to send this new data to Android app and will be displayed on the app immediately.
My question is
1) If I am using TCP, is it possible to keep the socket connection open even after sending one data to anticipate the subsequent transfers. Or do I need to close the connection after every single data transfer and set up another socket connection.
2) What is the latency of a TCP in the event I am performing something like these?
Any form of advice is greatly appreciated!
Most TCP implementations delay sending small buffers for a short period of time (~.2 seconds) hoping that more data will be presented before adding the expense of sending the TCP segment. You can use the TCP_NODELAY option to (mostly) eliminate that delay. There are several other factors that get in the way, such as where the stack happens to be in an ACK sequence, but its reasonably good way to get prompt delivery.
Latency depends on many factors including other traffic on the line and whether a given segment is dropped and needs to be retransmitted. I'm not sure what a solid number would be.
Sometimes real time data is "better never than late", making UDP datagrams a good option.
update: A TCP connection stays open until you close them with shutdown(), a client or server level socket timeout hits or the underlying stack finally gets bored and closes it. So normally you just connect and send data periodically over time. A common way to deal with a timed out socket is to reconnect if you hit a send error.

Android socket stable communication

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.

Categories

Resources