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