问题
I am experimenting with connecting my Galaxy Ace to my laptop via WiFi. Both devices are connected to a router via WiFi, and both sides use Java.
After a TCP connection gave me very high pings from time to time, I decided to base the connection on UDP, to be able to control when the packets are actually sent.
However, it seems like Android still buffers UDP packets and does not send them immediately. This, or it shuts down WiFi completely, if there is no outgoing data transmitted for some fraction of a second.
First, I pinged the phone at irregular intervals of about once a second, repeatedly sending ping requests, as long as no answer was received (covering packet loss in UDP):
computer -> phone -> computer
Pinging 192.168.1.40: 148.05968ms
Pinging 192.168.1.40: 524.41156ms
Pinging 192.168.1.40: 705.8688ms
Pinging 192.168.1.40: 3.705367ms
Pinging 192.168.1.40: 3.872159ms
Pinging 192.168.1.40: 549.4541ms
Pinging 192.168.1.40: 479.29843ms
Pinging 192.168.1.40: 3.89936ms
Pinging 192.168.1.40: 428.85876ms
Pinging 192.168.1.40: 739.28125ms
I worked around this problem by sending packets from phone to computer with just 1 byte of data every 100ms, changing nothing on the routine other than that:
computer -> phone -> computer
Pinging 192.168.1.40: 4.147753ms
Pinging 192.168.1.40: 3.738213ms
Pinging 192.168.1.40: 14.133768ms
Pinging 192.168.1.40: 4.470561ms
Pinging 192.168.1.40: 3.628386ms
Pinging 192.168.1.40: 3.898334ms
Pinging 192.168.1.40: 3.512401ms
Pinging 192.168.1.40: 7.907006ms
Pinging 192.168.1.40: 5.234216ms
Pinging 192.168.1.40: 5.639137ms
It is crucial for my application to have low latency, so I would keep sending empty packets like this (at least as long as there is no real data transmitted). I am wondering, if I can force android to respond as fast as possible, without needing to throw useless data all around the network. So, is there a more elegant solution?
By the way, I am assuming the problem is the smartphone, not the computer, though it could also be the computer waiting for incoming packets and then sending its packets. From what I know about networking, this is very unlikely, though.
Thanks for your help!
回答1:
As far as Java is concerned, once DatagramSockect.send(...) has been called, the datagram is "sent". There is no buffering in Java application space, and no way to control any buffering in the OS.
It is unlikely that either TCP or UDP is "holding back" packets. It is far more likely that the root problem is something at the WiFi level ... or possibly with routing ... and the OS is delaying sending the packets until the problem resolves itself.
Thanks, I now implemented sending those keep-alive packets only if there was no other packet sent during that time.
It sounds like your keep-alive pings are having the desired effect ... and from that I infer that the root problem is / was that the WiFi "link" was being dropped due to inactivity. (It sounds like a "don't drain the battery" feature ...) This suggests that an alternative fix would be to see if you can tweak the WiFi timeout.
Besides that, would it be faster to send packets to another port, on which nobody is listening? It should still have the same effect without, right?
It is unlikely to make any difference. There is no evidence that the problem is caused by congestion. The evidence points to your phone turning off inactive WiFi to save power ...
来源:https://stackoverflow.com/questions/13558283/force-android-to-send-udp-packets-immediately