TCP Send/Receive Problem

Started by
3 comments, last by TwistedPix 16 years, 11 months ago
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:


//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;
}


any help/suggestion is greatly appreciated. Thanks.
[Blog]
Advertisement
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:
            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.
[Blog]
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.
enum Bool { True, False, FileNotFound };
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]
[Blog]

This topic is closed to new replies.

Advertisement