Sign in to follow this  
TwistedPix

TCP Send/Receive Problem

Recommended Posts

TwistedPix    122
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.

Share this post


Link to post
Share on other sites
Antheus    2409
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.

Share this post


Link to post
Share on other sites
TwistedPix    122
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.

Share this post


Link to post
Share on other sites
hplus0603    11356
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.

Share this post


Link to post
Share on other sites
TwistedPix    122
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]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this