2010-12-09 64 views
0

我有这个代码,重点是我想使用UDP套接字接收不超过600Kbits/s,我实现了一个算法,使用期间,我们收到和睡眠命令....通过睡眠吞吐量控制

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

的问题是,它收到消息,但它会阻止接收过程中,不时......我猜会导致数据丢失尤其是当我使用的是UDP ...

任何替代解决方案是welcolme ...

在此先感谢..

+0

我们总是从零开始......到达顶端.. :) – fsidiosidi 2010-12-10 17:58:19

回答

0

如果您使用非阻塞套接字select(),则只有在准备好读取数据之前,您才可以忽略数据。不读取数据将导致TCP连接“减速”。但是,这样你可以做而不是对接收到的数据量有精确的控制。这只是一个近似值。所有我知道的以更准确的方式限制带宽的技术都是在发送端实现的。

1

最好不要睡觉 - 只需在超过阈值时读取并丢弃数据,然后在准备好后(间隔过期后)恢复处理。

+0

你能给出更多的解释...对于前,如何丢弃数据? – fsidiosidi 2010-12-10 17:54:54

+0

@fsidiosidi - 你只是按照现在的方式阅读它,但不要对它做任何事情。这样可以保持网络管道畅通,而不会在堆栈中丢弃任何数据。在你的示例代码中,你会绕过`printf`。您可以跟踪忽略数据的字节数,以查看忽略它的阈值是否合理。 – 2010-12-10 18:30:15

+0

但是这不会限制吞吐量..它只会丢弃到达的数据...我想收到不超过前:600kbits每次! – fsidiosidi 2010-12-13 10:47:11

1

如果数据通过UDP到达,则无法降低接收端的吞吐量。你必须告诉发送计算机发送更少的数据。接收者的唯一选择是接收UDP数据包,或者让它们丢弃,并且与它们做某事,或者不做。

如果使用TCP,那么TCP协议包含一个内置的方法来做你想做的事情(称为“源抑制”)......接收方的TCP协议层将发送一条消息给发送方,告诉如果接收器遇到问题,发件人会放慢速度。 (如果你愿意,你可以通过比平时更慢的速度读取数据来影响“接收器是否遇到问题”)。