0

My app sends small lines of text (commands to the server) or 32 bytes chunks of voice data. Right now I'm just using the socket's OutputStream's write. However, the problem is that Android Java seems to like to send the first byte by itself. Example:

  • Send: "Call Iron Man"
  • Received: "C", "all Iron Man"

To work around this splitting I prefix each line with a "throw away" character #. So the previous example is sent as:

  • Send: "#Call Iron Man"
  • Received: "#", "Call Iron Man" --> "Call Iron Man" will be used and "#" is ignored.

The problem becomes when I want to send 32 bytes of voice, it is sent as one packet of 1 byte, and then one packet of 31 byte. These 1 byte packets waste a lot of data because of the TCP/IP overhead. According to Sizing Source that means I will use (64+1) + (64+31) = 160 bytes for my 32 byte voice chunk when I could be using 64+32 = 96. That means I will be using 1.67X more LTE data than I should which (in Canada) will cost me a very pretty penny.

Is there a way to force all 32 bytes to be sent as one packet?


Here is the Android code for sending:

int totalRead = 0, dataRead;
while (totalRead < WAVBUFFERSIZE)
{//although unlikely to be necessary, buffer the mic input
    dataRead = wavRecorder.read(wavbuffer, totalRead, WAVBUFFERSIZE - totalRead);
    totalRead = totalRead + dataRead;
}

int encodeLength = AmrEncoder.encode(AmrEncoder.Mode.MR122.ordinal(), wavbuffer, amrbuffer);
try
{
    Vars.mediaSocket.getOutputStream().write(amrbuffer, 0, encodeLength);
}
catch (Exception e)
{
    Utils.logcat(Const.LOGE, encTag, "Cannot send amr out the media socket");
}

Here is the C/C++ code for receiving:

mediaRead = 0; //to know how much media is ACTUALLY received. don't always assume MAXMEDIA amount was received
bzero(bufferMedia, MAXMEDIA+1);
alarm(ALARMTIMEOUT);
do
{//wait for the media chunk to come in first before doing something
    returnValue = SSL_read(sdssl, bufferMedia, MAXMEDIA-mediaRead);
    if(returnValue > 0)
    {
        mediaRead = mediaRead + returnValue;
    }
    int sslerr = SSL_get_error(sdssl, returnValue);
    switch (sslerr)
    {
        case SSL_ERROR_NONE:
            waiting = false;
            eventful = true; //an ssl operation completed this round, something did happen
            break;
        //other cases when necessary. right now only no error signals a successful read
    }
} while(waiting && SSL_pending(sdssl));
alarm(0);
if(alarmKilled)
{
    alarmKilled = false;
    cout << "Alarm killed SSL read of media socket\n";
}                   

where MAXMEDIA = 1024 so there is definetly enough place for the 32 bytes of voice data

jww
  • 97,681
  • 90
  • 411
  • 885
AAccount
  • 49
  • 7
  • Unanswerable without seeing your code, but you certainly don't need to add junk at the beginning of your data. Your real problem is almost certainly at the receiving end. – user207421 Jul 02 '16 at 01:05
  • OK added in both the relevant server and android code. – AAccount Jul 02 '16 at 03:24
  • 1
    Your reading code appears to assume that only one read should be necessary. There is no guarantee in TCP about that. – user207421 Jul 02 '16 at 03:48
  • Also see [Android TCP communication is too slow](http://stackoverflow.com/q/30813864). Maybe [Silly window syndrome](http://en.wikipedia.org/wiki/Silly_window_syndrome)? – jww Jul 02 '16 at 11:29

0 Answers0