2010-12-09 62 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協議層將發送一條消息給發送方,告訴如果接收器遇到問題,發件人會放慢速度。 (如果你願意,你可以通過比平時更慢的速度讀取數據來影響「接收器是否遇到問題」)。