Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

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

Posted on 1999-07-12
23
Medium Priority
?
270 Views
Last Modified: 2010-04-02
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
Comment
Question by:sun307
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
23 Comments
 
LVL 6

Expert Comment

by:MichaelS
ID: 1199863
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
 
LVL 2

Author Comment

by:sun307
ID: 1199864
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
 
LVL 6

Expert Comment

by:MichaelS
ID: 1199865
So looks like that you sent all data and receive all data. In such case the problem is not in sockets.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 4

Expert Comment

by:pellep
ID: 1199866
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
 
LVL 3

Expert Comment

by:PinTail
ID: 1199867
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
 
LVL 2

Author Comment

by:sun307
ID: 1199868
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
 
LVL 2

Author Comment

by:sun307
ID: 1199869
I am already using TCP and using Compression/decompression also which is what i meant with processing the data.
0
 
LVL 6

Expert Comment

by:MichaelS
ID: 1199870
What's about buffers algorithm? With voice chat I used a lot of buffers.
0
 
LVL 2

Author Comment

by:sun307
ID: 1199871
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
 
LVL 6

Expert Comment

by:MichaelS
ID: 1199872
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
 
LVL 3

Expert Comment

by:Iexpert
ID: 1199873
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
 
LVL 2

Author Comment

by:sun307
ID: 1199874
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
 
LVL 2

Author Comment

by:sun307
ID: 1199875
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
 
LVL 6

Expert Comment

by:MichaelS
ID: 1199876
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
 
LVL 2

Author Comment

by:sun307
ID: 1199877
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
 
LVL 6

Expert Comment

by:MichaelS
ID: 1199878
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
 
LVL 2

Author Comment

by:sun307
ID: 1199879
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
 
LVL 6

Expert Comment

by:MichaelS
ID: 1199880
You named it.
0
 
LVL 2

Author Comment

by:sun307
ID: 1199881
Hi MichaelS !
I didn't get this line :
*((int*)m_pData=iSize;
what this will do ?
0
 
LVL 2

Author Comment

by:sun307
ID: 1199882
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
 
LVL 6

Expert Comment

by:MichaelS
ID: 1199883
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
 
LVL 2

Author Comment

by:sun307
ID: 1199884
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
 
LVL 6

Accepted Solution

by:
MichaelS earned 1000 total points
ID: 1199885
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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question