• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 272
  • Last Modified:

Receiving Data (Sockets) - Experts Please Help....

Hi !
I am building a voice chat application for which I am required to receive packets of data containing voice in a consistent manner. i.e. I have to receive each packet without any loss. The size of my voice packets is fixed which is 845 bytes. I am using threads for both sending and receiving the data. The problem is that the data reaching on destination is lost somewhere and maybe (i am not sure) the data from the next packet got appended to the previous one thus spoiling the whole packet.

Following is the code to send and receive the data. both are threads. The threads to receive the data is started in the beginning of application and works till the application is continued.

//Code to send the data
//As soon as a buffer is filled with audio the following //thread is started and is passed the audio data in the //form of one of the data member of structure PADATA
void sendAThread(PADATA tInfo)
{
WaitForSingleObject(hSendMutex,INFINITE);
char sc[40];
int arc=send(tInfo->r_socket,(char*)tInfo->buffer,tInfo->br,0);
ReleaseMutex(hSendMutex);
return;
}


//code to receive the data

void ReceiveAudio()
{
int rrc;
int tb;
char s[40];
char buffer[845];
int nsize;

for(;;)
{
nsize=845;
tb=0;
do
{
rrc = recv(remote_socket,(char*)(&(buffer[tb])), nsize,0);      if(rrc>0)
      {
      nsize=nsize-rrc;
      tb=tb+rrc;
      }
}while(nsize>0);

if(tb==845)
{
//Process the bufer
}

}
      return;
}



Will it help if insted of sending the buffer, first i put into a structure and then pass it to the socket on other side.

As far as LAN is concerned the application is running fine on that.
0
sun307
Asked:
sun307
1 Solution
 
MichaelSCommented:
The problem is that when you call send you can send not all packet, just part of it. So you have to chek is all packet sent and if not try to send the rest like you did it with receive.
0
 
sun307Author Commented:
Hi MichaelS !
As u say that the problem can be with send(). I am displaying the value of arc ( arc=send(....)) in a list box and found that it always comes out to be 845 bytes which i want to sent. So, I don't think that the problem could be with that. Anyway, as a precaution I am implementing the solution suggested by u.
0
 
MichaelSCommented:
So looks like that you sent all data and receive all data. In such case the problem is not in sockets.
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
pellepCommented:
Are you using TCP or UDP type socket? If you are using UDP, then the protocol does not guarantie that the packets are received in the same order as they were sent.
0
 
PinTailCommented:
Typically one does not merely just recv data, and then not validate it in some way.  As a minimum you ought to be numbering each packet of data and verifying that you are receiving them all.

If not you will probably want some strategy to deal with lost packets - maybe request they be retransmitted -

Also, with voice data, you will undoubtably be using some form of data compression, and lost packets usually corrupt the compression scheme.  


The other thing to consider is what whas previously been mentioned: there is no guarentee that a single call to send() will transmit the entire buffer, that is why it returns a value, so that you can check it and send the rest of the data if necessary. ( you do this with recv(), why be inconsistant with send() )

Can you use TCP ??  this eliminates a very many problems, and will work suitably over a high speed LAN.

0
 
sun307Author Commented:
Hi !
I had modified my sendAThread() as follows but the problem still continues :

void sendAThread(PADATA tInfo)
{
WaitForSingleObject(hSendMutex,INFINITE);
int trc = 0;
int arc = 0;
char sc[40];

while(trc<GSMBS)
{
      tInfo->r_socket +=trc;
      arc=send(tInfo->r_socket,(char*)tInfo->buffer,tInfo->br,0);
      if(arc == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
      {
            ReleaseMutex(hSendMutex);
            return;
      }
      trc +=arc;
}

ReleaseMutex(hSendMutex);
return;
}

0
 
sun307Author Commented:
I am already using TCP and using Compression/decompression also which is what i meant with processing the data.
0
 
MichaelSCommented:
What's about buffers algorithm? With voice chat I used a lot of buffers.
0
 
sun307Author Commented:
Hi MichaelS !
I am using 4 buffers to record the voice and two buffers for playing it. Can u put some light on how to play with more than two buffer and give some more tips on bringing efficiency to audio chat software.
0
 
MichaelSCommented:
Ok, a few words about how I play data. Initialy I have only two buffers for playing. I put them to linked list. When I receive new data for playing I serch to free buffer. If there is - I use it. If there are not free buffers I create a new one and use it.
Of course it's a cheep trick, but at least it works.
0
 
IexpertCommented:
You need to add a header when sending
and read this when receiving to make sure you
only read 1 packet at a time
0
 
sun307Author Commented:
Hi lexpert!
Should I do this using a structure or should i add some header value at the start of my sound buffer which is an array.

0
 
sun307Author Commented:
Hi MichaelS!
I myself is using a linked list to store the received data and this way adding nodes dynamically. when i receive 6 buffers initially i started playing them checking the items remained to be played in the list. If there is no buffer left i stop the playing of data unless 6 more buffer got added and the process is repeated but the real problem i am facing is with receiving of buffers. I think that some part of them are getting lost. How are u receiving the buffer and doing the error checking whether the buffer is complete one or without any problems. Kindly put some light on this.
0
 
MichaelSCommented:
I used different buffer size and cos of this I used buffer header. Something like

class CBuffer:
{...
    int     m_iSize;
    LPSTR   m_pBuffer;
};
I send m_iSize and after that m_pBuffer. When I receive buffer first of all I receive int value which indicate how many bytes I have to receive... If you use TCP/IP it should be not porblems with "losting".


0
 
sun307Author Commented:
hi MichaelS !
thanx for all this information. I will implement the above solution of putting the data in a structure with a fixed header as my buffer size is fixed. Now some more clarifications :
1. Are u sending the object of CBuffer or sending it's member i_Size first and then m_pBuffer using separate send() command one after another. if u r sending i_Size first and then m_pBuffer then how to distinguish that the received data is i_Size or m_pBuffer.

2. what should be the ideal size of buffer for voice transmission or it should depend on the time like my current buffer is of 0.52 seconds and is of size 845 bytes.
Should I decrease the size or not ?
0
 
MichaelSCommented:
Actually I have something like
class CBuffer:
{    ....
     void SetData(LPSTR szData, int iSize)
     {    m_pData = new char[iSize + 1 + sizeof(int)];
          strncpy(m_pData, szData, iSize);
          *((int*)m_pData) = iSize;
     }
     
     LPSTR GetData()
     {    return m_pData + sizeof(int);
     }
};

I use one call of send if it's send all data, if not - more. At receive side I make something like

recv( , , sizeof(int), );
and after that I know how much data I have to receive to buffer.
0
 
sun307Author Commented:
Hi MichaelS !
Thanx for quick response. Does the code above meant that you are appending the size of buffer at the start of string containing the voice data and then on the other side u r first getting this particular no. of bytes containing the size and the voice data in next attempt.
0
 
MichaelSCommented:
You named it.
0
 
sun307Author Commented:
Hi MichaelS !
I didn't get this line :
*((int*)m_pData=iSize;
what this will do ?
0
 
sun307Author Commented:
Hi MichaelS!
Today I found a very strange thing. I am usig GSM codec for compression/decompression. I am directly recording the audio in compressed form in GSM 6.10 format and decompressing it before playing. All this is running fine on LAN.

I am processing my MM_WIM_DATA message like this :

case MM_WIM_DATA:
buffer=(char*)((LPWAVEHDR)lParam)->lpData;
sprintf(ss,"SIZE OF BUFFER IS %d",strlen(buffer));
Display(ss); //function to display the ss in listbox
br=((LPWAVEHDR)lParam)->dwBytesRecorded;
sprintf(ss,"BYTES RECORDED = %d",br);
Display(ss);
waveInUnprepareHeader((HWAVEIN)wParam,(LPWAVEHDR)lParam,sizeof(WAVEHDR));
waveInPrepareHeader((HWAVEIN)wParam,(LPWAVEHDR)lParam,sizeof(WAVEHDR));
waveInAddBuffer((HWAVEIN)wParam,(LPWAVEHDR)lParam,sizeof(WAVEHDR));
return TRUE;
break;

Now , the thing is that 0.52 seconds of data in GSM format takes 845 bytes. But as I am displaying both the length of buffer and bytes recorded, both display different values.
The value of =((LPWAVEHDR)lParam)->dwBytesRecorded; always comes out to be 845 for each buffer while strlen(buffer) give different values for each buffer. If i am not speaking into microphone it gives something like 35 or 58 (mean some less value) and when i speak loudly in microphone it gives 845 or say close to that. Can u explain this phenomenon.

As i am taking the buffer size constant equal to 845 bytes and using the send() and recv() command to send and receive exactly 845 bytes. isn't that a problem. But i am puzzled that, in that case the application should not run on LAN as well.

Kindly explain this.

I might be bothering u with so many questions, but i will increase the points for u which u fully deserves.
 

0
 
MichaelSCommented:
Hi, I am not sure about dwBytesRecorded in GSM standard, but for me it looks like there is no problem cos it works on LAN. Probably you have to check your algorithm again. I not really get your output way. Why you waiting for 6 buffers to start paying? Why not play as soon as you receive buffer?
0
 
sun307Author Commented:
Thanx MichaelS !
with your help the application is running fine on Internet too. Can u comment on CODECS like which one is best as far as quality of voice retained is concerned.
Propose as Answer so that Question can be closed.
With Regards :-
Sun307
0
 
MichaelSCommented:
Codecs is a very intresting question. First of all you can (official) use only standard codecs which came with win95 or NT or... As I know it's very complex to write your own codec. And it's very expensive to buy it. If you develop a voice chat application I think it's good idea to make it H.323 compatible. In such case you have to support G.711, G.723 and G.729 codecs. There are a lot of sites about H.323 in the web.
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now