I have a problem with receiving UDP packets. My environment is running Android 2.1 on ARMv7. With C socket programming, I use recvmsg to receive packets from kernel but occasionally there are some packet loss events. The sender and receiver are in the same LAN so it's no doubt that packets shouldn't lose. And I proved it via Wireshark.
However, after I replaced recvmsg with recvfrom to receive packets, packet loss event didn't occur anymore.
I'm sure the return value of recvmsg is always more than 0, meaning no error happens.
Is it possible that some packets are dropped in kernel-space only when using recvmsg ?
Yes, it's possible. UDP is unreliable. If dropping of UDP datagrams is creating a problem, then something is very wrong with your design.
Check your socket for drops via cat /proc/net/udp.
This recv man page seems to indicate that recvmsg does not block, while recvfrom does block, at least by default. It's possible that you are calling recvmsg and there are no packets available at that moment. If you called it repeatedly I suppose you might see all your packets eventually just like you did in wireshark.
Related
I'm working on an Android application which sends/receives a high volume of UDP traffic to a Windows endpoint over a WLAN (and no, I can't use TCP).
The problem is that when I ramp up the traffic, I begin to see HUGE delays between when I call sendto (the app is written with the NDK) and when I see the packet arrive at the Windows endpoint. In the neighborhood of 10 seconds! The same thing happens in reverse too: I see huge delays between the packet being sent by the Windows endpoint and being picked up by recvfrom().
Changing SO_SNDBUF has no effect, so I don't think it's an issue with the application-level buffering control.
I've verified that the problem exists on a variety of Android devices, so I don't think it's an issue with the hardware/wireless drivers
Using a sniffer and correlating the timestamps, I confirmed that the delay is occurring between calling sendto() and the packet being sent from the Android device, so the buffering isn't happening in the AP or Windows endpoint
So at this point I'm all but out of ideas. The facts would lead me to believe that the buffering is happening on the Android OS layer, but 10 seconds of 10Mbps traffic? That seems too high to be feasible for an OS where memory footprint is such a huge concern.
Also, if the issue is that I'm sending data too fast and overwhelming the OS, then I would expect sendto() to return ENOMEM or ENOBUFS... But there are no indications that anything is wrong on the Android application level.
So my question is: what's causing this delay? And is there a way to mitigate it, or do I need to alter my application to have longer timeouts or some way of detecting this condition before it gets bad?
You are sending too much.. how much are you sending? 10Mbps is definitely way too high. Bear in mind:
Every UDP datagram you send has an additional 28 byte header (UDP + IP over IPv4)
Connection link speeds are theoretical maximum limits that you will never be able to achieve
The Phone OS could be limiting you, Phone OS's need to conserve battery and try to minimise socket comms to do so.
OR
You say your CPU is at 20%, how many cores do you have - you could be maxing out the core that is doing the sending, i.e. processing speed is the bottleneck.
For people with the same problem:
Try reusing the DatagramSocket. That solved it for me.
I've seen reports of very similar behavior on the linux-rt list lately, which may be related.
http://comments.gmane.org/gmane.linux.rt.user/10163
For a several months I was haunted with spurious jitter, detected on
UDP messages - multicast UDP messages where received on originating
node without any delay, but on other nodes a delay in range of 10s of
milliseconds was detected. Simply, it looked like a message was stuck
in kernel before finally getting transmitted.
Finally, thanks to LTTng tool, I was able to locate the problem down to
this peace of code in net/sched/sch_generic.c:
There appears to be a locking issue on transmit that causes the tx stall.
I am facing weird problem in receiving udp packets on Sony Xperia Z tablet. My application didn't receive many udp packets. So I have rooted the tablet to install the shark app and captured the network traffic using shark app after rooting the device. When I analyzed the report, the device has received all the packets but my application did not receive many of them. If the application didn't receive any packets, issue could be the packet filter which blocks broadcast packets. Here, my application receives few packets but misses packets received by device. I have not observed this issue with samsung tab 2 and motorola xoom tablet where it receives all the packets. It sounds like there is no code issue. Have anybody faced similar problem? Let me know if you have any suggestions or inputs that I can try.
UPDATE:
I have added my comments below.
I'd tell you a UDP joke, but you might not get it.
Packet loss is a documented feature of the UDP protocol.
UDP protocol does not guarantee that the package will be delivered to the addressee.
http://en.wikipedia.org/wiki/User_Datagram_Protocol
I have found why my app missed some packets received by device. I have set datagram socket receiver buffer size to small value. I removed this code setting buffer size and then it strated receving all the packets. By default, android sets buffer size as 163840B but I set the size to 64 bytes. It is working fine with default buffer size set by 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.
I have problem with socket communication - > SIP server and android devices.
I can’t send SIP packet over TCP bigger than 800 bytes.If the packet is < 800 bytes everything is OK. There is a successful TCP handshake established before try to send SIP packet and still nothing.
I send the data like this way;
Socket socket = new Socket(ip,port);
OutputStream out =new OutputStream(socket.getOutputStream());
out.flush();
out.write(msg);
There is no problem with send function. Strange thing is that some packets are delivered to server minutes after being send from devices for SIP packets > 800 bytes.
If we try to send other data not SIP with size of packet > 800 bytes everything is OK and server receives it. The problem is only with SIP packets > 800 bytes. This problem happens not for all android devices. For example:
Galaxy s plus – problem.
Nexus 4 – problem.
Nexus s – no problem. and etc.
The issue is resolved if I split the SIP packet at two parts, however I would like to find out why SIP data isn’t flushed and other data is sent immediately. There shouldn’t be any difference.
You didn't provide information about versions, but I bet you have the problem in Android's 4.0.*.
I also bet the problem only happens when you use the port 5060 over TCP.
That is a known problem in those Android versions, and the current workaround is either to update to Android 4.1(and you can't ask users to do that!) or to avoid those settings.
Any other port or UDP will work.
You can find here one bug report.
Ok, so here's my problem. I have an android app transmitting UDP packets to a PC (a java program which listens for the packets), based on user interactions with the android device. To keep things simple, let's say this is happening - the user taps the screen of the phone, and it sends a UDP packet with the coordinates of the point where the user tapped. The listener program receives and reads this packet, and outputs the string received, using System.out.println().
Now, what's happening is that the program works perfectly for the first few packets. Then it stops working, as in, the listener program on the desktop does not display any output. Now, the issue is probably with the transmission, as I have a text label on the app (for testing purpose) that displays what is being transmitted, so the transmission packet is definitely being built properly. But I have no idea on how to understand if this is a problem with sending the data (on the android device side), or receiving (on the desktop side). How can I find out what's wrong and solve this issue?
I have mostly worked with TCP transmission and all the UDP i have done are mostly Copy-Paste [:-)] or with APIs
For TCP, after transmission, I throw a debug message, which helps me to know that the transmission occurred properly. But in this case, your write will have to be blocking.
Also, you could use a Packet Tracer on your listener terminal to determine whether it is receiving the packets properly. The one I love is WireShark (I think its a fork of Ethereal). Its really easy to use. You tell it which interface to listen on and give a filter and it will list out the packets as and when they come.
However, if you are using Windows 7, you will need admin privileges.
Are you using native code or Java classes? I have tried both, and with the NDK (i.e. sockets written as C functions being called from Java) I have seen erratic behavior on the server side, mostly due to threading issues. Using the Java Socket class I have not had issues however. Moreover, if your Android app is the client, that should not be the problem. I would also use Wireshark to check whether the packets are reaching the PC.