java - Very slow sockets on Android over wifi -
i'm having performance problem consistent speed of tcp socket connection between 2 android tablets talking on wifi on same lan. (just enough real problem), round-trripping small payload (< 1400 bytes) between devices can take many seconds. it's not uncommon take 10+ seconds, , in worst case, i've seen round trip time of 4 minutes. socket not broken - it's typically blocking on read operation @ client or server end, , once round trip completes, next 1 take few milliseconds.
if continuously push data through socket, not see problems, , typically remain fast ( < 100ms) , connected day long. however, when drip feed payloads - 1 every couple of seconds, not each round trip take longer, occasionally, see these silly times of 10 seconds or more. i'm not looking high performance, , 3 seconds not problem.
i understand pauses between payloads, android preserve battery briefly turning off wifi radio, , tcp stack may add small delay give app layer time add bit more data payload. these 2 points explain ~120ms rountrips versus 1-5ms roundtrips when payloads sent continuously. however, i've never heard of tcp hanging onto buffered data 30+ seconds before sending.
this not nagle issue - tcp_no_delay set true, , i've played thread priorities , other tcp tuning flags no avail.
i'm using 2 samsung galaxy tabs running lollipop , marshmallow, though have tried asus, archos, lenovo , huawei devices.
there's nothing fancy going on - writing socket looks this:
try { clientsocket = new socket(serverip, echo_port); sockettransport transport = new sockettransport(clientsocket); while (running) { // blocking call ;-) onstatuschange("waiting next message", 0); string msg = theq.take(); onstatuschange("writing new message", 0); long timestart = system.currenttimemillis(); transport.write(msg); onstatuschange("waiting response", 0); string result = transport.read(); onstatuschange(result, system.currenttimemillis() - timestart); if (result == null) { running = false; } } } with actual read & writing happening in simple wrapper class looks this:
package com.problem.sockettester; import java.io.bufferedinputstream; import java.io.bufferedoutputstream; import java.io.datainputstream; import java.io.dataoutputstream; import java.io.ioexception; import java.net.socket; /** * wrap reading , writing sockets. */ public class sockettransport { static final int iptos_lowcost = 0x02; static final int iptos_reliability = 0x04; static final int iptos_throughput = 0x08; static final int iptos_lowdelay = 0x10; private datainputstream reader; private dataoutputstream writer; private byte[] readbuffer = new byte[4096]; public sockettransport(socket socket) throws ioexception { socket.setkeepalive(true); socket.settcpnodelay(true); socket.settrafficclass(iptos_lowdelay | iptos_reliability); socket.setreceivebuffersize(4096); socket.setsendbuffersize(4096); reader = new datainputstream(new bufferedinputstream(socket.getinputstream())); writer = new dataoutputstream(new bufferedoutputstream(socket.getoutputstream())); } public string read() throws ioexception { int messagesize = reader.readint(); int bytesread; int totalread = 0; int offset = 0; boolean moretoread = true; while (moretoread) { bytesread = reader.read(readbuffer, offset, messagesize); totalread += bytesread; if (totalread == messagesize) { moretoread = false; } offset += bytesread; } return new string(readbuffer, 0, messagesize); } public int write(string message) throws ioexception { writer.writeint(message.length()); writer.writebytes(message); writer.flush(); return message.length(); } } for challenge, full source of minimal server , client apps can found on github @ https://github.com/nigeldyson/androidsocketissue
any ideas or appreciated - i'm fast running out of ideas.
Comments
Post a Comment