Click here to Skip to main content
15,895,833 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi everyone,

I have this code, the point is that I want to receive no more than 600Kbits/s using a UDP socket, I implemented an algorithm using duration during which we receive and the sleep command....

#if defined (WIN32)
    #include <winsock2.h>
    typedef int socklen_t;
#elif defined (linux)
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #define INVALID_SOCKET -1
    #define SOCKET_ERROR -1
    #define closesocket(s) close(s)
    typedef int SOCKET;
    typedef struct sockaddr_in SOCKADDR_IN;
    typedef struct sockaddr SOCKADDR;
#endif

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define RCVBUFSIZE 4
#define PORT 4444
#define ECHOMAX 255

int main(void)
{
    #if defined (WIN32)
        WSADATA WSAData;
        int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
    #else
        int erreur = 0;
    #endif

    int recvMsgSize;
    char echoBuffer[RCVBUFSIZE];
    //unsigned int echoStringLen;
    //int bytesRcvd, totalBytesRcvd; //bytes received in a single recv()

    SOCKET sock;
    SOCKADDR_IN sin;
	SOCKADDR_IN SenderAddr;
	int SenderAddrSize = sizeof(SenderAddr);


    if(!erreur)
    {

        sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        sin.sin_addr.s_addr = inet_addr("127.0.0.1");
        sin.sin_family = AF_INET;
        sin.sin_port = htons(4444);
		memset(&sin.sin_zero, '\0', sizeof(sin.sin_zero));

         bind(sock, (SOCKADDR*)&sin, sizeof(sin));

    //totalBytesRcvd = 0;

    printf("Received: ");
    
    int speed_limit= 614400; //600Kbits/s
    int one_second=1000;
    int elapsed; //elapsed time
    int transmit=0; // how much i receive during 'elapsed'
    int expected_receive; //what I'm excpected to receive
    int transmit_delta; //diference
    int time_sleep; //how much to sleep
    clock_t start_time= clock();

     for(;;)
    {


        if((recvMsgSize=recvfrom(sock, echoBuffer,1024, 0, (SOCKADDR *)&SenderAddr, &SenderAddrSize)) > 0)
        {
                transmit+=recvMsgSize;
                clock_t tempo= clock();

                elapsed=(tempo-start_time)/CLOCKS_PER_SEC;
            // Check moment speed every five second, you can choose any value
                if(elapsed>5)
                {
                    start_time= tempo;
                    expected_receive=speed_limit*elapsed/8;
                    transmit_delta=expected_receive-transmit;

                    if(transmit_delta>0)
                    {
                        time_sleep=8*transmit_delta*one_second/speed_limit;
                        Sleep(time_sleep);
                    }
                    transmit=0;
                }
                echoBuffer[recvMsgSize]='\0';
                printf(echoBuffer);


        }

    }
        printf("\n");
        getchar() ;

    closesocket(sock);
    
        #if defined (WIN32)
            WSACleanup();
        #endif
    }

    return EXIT_SUCCESS;
}


the problem is that it receive the message but it blocks the receiving process from time to time...which I guess will cause loss of data especially when I'm using UDP...

any alternative solution is welcolme...

thanks in advance..
Posted

1 solution

You'll only lose data with recvfrom if your buffer is too small.
You can avoid having a too small buffer by calling recvfrom with MSG_PEEK argument to check the required buffer size without removing any data from the queue (you can read how to do this here[^]).
 
Share this answer
 
v3
Comments
fsidiosidi 9-Dec-10 12:05pm    
what do you mean by the buffer? is it the buffer of the socket or my buffer "echoBuffer" where I put my received data?....and I'm wondering if the option SO_RCVBUF of the socket will help?
[no name] 9-Dec-10 12:24pm    
The buffer is echoBuffer. In the msdn page it says, "If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recvfrom generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost."
To prevent this, you can call recvfrom with a MSG_PEEK argument, to know exactly how large a buffer you need.

The required size of socket buffer depends on the bitrate of your input; it should be at least big enough to hold a number of bits equal to the bit/s of the input over 600Kbits/s multiplied with how long this can happen. For example if your input can be 700Kbits/s for at most 5 seconds, you'd need (700K-600K)*5 = 500Kbit in your buffer. If your input can be above 600Kbits for an unspecified amount of time, it's not possible to predict how large a buffer you need.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900