Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ Threading socket
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 9-Dec-10 5:53am

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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[^]).
  Permalink  
v3
Comments
fsidiosidi at 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?
Thaddeus Jones at 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)

  Print Answers RSS
0 OriginalGriff 240
1 Kamal Rocks 184
2 PIEBALDconsult 150
3 BillWoodruff 148
4 Jochen Arndt 135
0 OriginalGriff 5,695
1 DamithSL 4,506
2 Maciej Los 4,007
3 Kornfeld Eliyahu Peter 3,480
4 Sergey Alexandrovich Kryukov 3,190


Advertise | Privacy | Mobile
Web02 | 2.8.141216.1 | Last Updated 9 Dec 2010
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100