//Sender
void TCPRenderer::SendFrame()
{
unsigned short TotalSize = 0;
unsigned short TmpSize = 0;
int Offset = 0;
int UShortSize = sizeof(unsigned short);
char* Buffer = NULL;
TotalSize = (UShortSize * 3) + (USHORT)sizeof(NetData) + (USHORT)m_mt.cbFormat + m_BufferSize;
Buffer = new char[ TotalSize + UShortSize ];
ZeroMemory(Buffer, TotalSize + UShortSize);
ZeroMemory(&Sample, sizeof(Sample));
Sample.MediaType = m_mt;
Sample.SampleProp = m_SampleProps;
//Add Total Size
memcpy(Buffer, &TotalSize, UShortSize);
Offset = UShortSize;
//Add Remainig Data Sizes
TmpSize = sizeof(NetData);
memcpy(Buffer + Offset, &TmpSize, UShortSize);
Offset += UShortSize;
TmpSize = (unsigned short)m_mt.cbFormat;
memcpy(Buffer + Offset, &TmpSize, UShortSize);
Offset += UShortSize;
TmpSize = m_BufferSize;
memcpy(Buffer + Offset, &TmpSize, UShortSize);
Offset += UShortSize;
//Add Actual Data
memcpy(Buffer + Offset, &Sample, sizeof(Sample));
Offset += sizeof(Sample);
memcpy(Buffer + Offset, m_mt.pbFormat, m_mt.cbFormat);
Offset += m_mt.cbFormat;
memcpy(Buffer + Offset, m_Buffer, m_BufferSize);
Offset += m_BufferSize;
//Send & clean up
Send(Buffer, TotalSize + UShortSize );
DELETE_ARRAY(Buffer);
}
//Send
void TCPRenderer::Send(const char *Buffer, int Size)
{
int sended = 0;
while(sended < Size)
{
int ret = m_Sender.Send((char*)Buffer + sended, Size - sended);
if(ret == SOCKET_ERROR)
{
PrintWinsockError();
return;
}
sended += ret;
}
}
//Receiver
int TCPSourceStream::ReadNetworkData()
{
bool FirstPacket = true;
char* Buffer = 0;
USHORT Size = 0;
USHORT TotalReceive = 0;
int Received = 0;
while(true)
{
if(FirstPacket)
{
char cSize[sizeof(USHORT)];
Received = m_Receiver.Receive(cSize, sizeof(USHORT));
ON_WS_ERROR(Received);
memcpy(&Size, cSize, sizeof(USHORT));
//Error occurred
if(Size > g_MaxPacketSize)
{
printf("Packet Size (%u) Exceeded the maximum packet size (%d)", Size, g_MaxPacketSize);
return -1;
}
Buffer = new char[ Size ];
ZeroMemory(Buffer, Size);
FirstPacket = false;
continue;
}
Received = m_Receiver.Receive(Buffer + TotalReceive, Size - TotalReceive);
ON_WS_ERROR(Received);
TotalReceive += Received;
if(TotalReceive > Size)
{
printf("TotalReceive (%u) Exceeds Packet Size(%u) \n", TotalReceive, Size);
DELETE_ARRAY(Buffer);
return -1;
}
if(TotalReceive == Size)
{
//Delete any previous aloocated buffers
DELETE_ARRAY(m_Buffer);
m_Buffer = Buffer;
break;
}
}
return Size;
}
TCP Send/Receive Problem
Hello all
I am working on video conferencing application which sends data 15-30 times per second. it works fine on my machine ( loop back IP ) or on lan. but when i run it on real network it will crash after several minutes. i found out that prefixing length i attached to the data get messed.
my question is, is it possible some additional bytes attached to my data?
or i missed some point about tcp?
and how can i reset tcp buffer? is it possible?
btw i'm using blocking sockets atm.
here is my send and receive algorithm:
any help/suggestion is greatly appreciated.
Thanks.
What does m_Receiver.Receive do?
There is no reason why socket receive couldn't return a single byte. Yet there you assume you'll receive 2 bytes, and don't check afterwards if you really did.
The code I'm referring to:
Unless it's blocking call that reads until specified number of bytes is made available, but in that case, you wouldn't be running the loop.
The only suspicious thing I do see here is that. Try checking if m_Receiver.Receive actually reads 2 bytes.
There is no reason why socket receive couldn't return a single byte. Yet there you assume you'll receive 2 bytes, and don't check afterwards if you really did.
The code I'm referring to:
char cSize[sizeof(USHORT)]; Received = m_Receiver.Receive(cSize, sizeof(USHORT));
Unless it's blocking call that reads until specified number of bytes is made available, but in that case, you wouldn't be running the loop.
The only suspicious thing I do see here is that. Try checking if m_Receiver.Receive actually reads 2 bytes.
i put recv() and some other winsock stuff in one class (m_Receiver). i used Blocking mode for simplicity but as you said that will wait until specified number of bytes is available.
I'll check returned size too.
Thanks for your help.
I'll check returned size too.
Thanks for your help.
Quote:i used Blocking mode for simplicity but as you said that will wait until specified number of bytes is available.
In the underlying WinSock implementation, it does not. If there is any data to return, it will return that data, even if it's not the full buffer you asked for. It will only block if there is no data in the buffer.
I don't know if the C# library changes this semantic or not. The semantic you're describing is that of the UNIX read() system call, which will return the entire buffer, unless the stream is closed.
The "etwork" networking library (pointed at from the Forum FAQ) correctly implements length-delimited packets over TCP, and handles the case of getting a single byte out of a two-byte header (which, btw, was an annoying case to get right :-) You can check that source for inspiration if you want.
Quote:Original post by hplus0603
In the underlying WinSock implementation, it does not. If there is any data to return, it will return that data, even if it's not the full buffer you asked for. It will only block if there is no data in the buffer.
yes my problem was exactly that, i didn't checked the return value of recv() function.
Thanks Antheus and hplus0603 for your great help ( btw i had this problem for one month and was wondering what's really wrong ) :)
[Edited by - TwistedPix on May 10, 2007 7:30:26 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement