(原)關於udp的socket發送數據耗時的問題探討

轉載請註明出處:http://www.cnblogs.com/lihaiping/p/6811791.htmlhtml

本學習筆記,僅用於問題探討,若有不一樣,能夠討論。服務器

 

最近在看流媒體分發服務器的相關代碼,其中對於網絡udp數據發送耗時的研究,這塊有一點點疑問:網絡

udpsendto發送數據的耗時大概爲多少?他的耗時跟發送的數據包大小有沒有關係?跟對端的ip地址是否存在,有沒有關係?是否存在ip地址在的網絡,sendto耗時小,對於ip地址網絡不通的耗時是否是比較大?less

 

網絡搜索,csdn論壇有人問了:http://bbs.csdn.net/topics/60039818socket

 

而後我拷貝了論壇的測試程序,在vs上運行測試了一把,同時進行了部分修改。函數

 

//測試網絡發送耗時問題
int udp_socket_send_test(int argc, char* argv[])
{
    DWORD    LastTime;
    DWORD    Curtime;
    DWORD    EscpTime;
    WSADATA        wsaData;
    long    addr;
    long    wrc;
    long    lngSendTimeOut = 1000;
    long    lngRecvTimeOut = 1000;
    SOCKADDR_IN sockObject;
    SOCKET    sSend;
    u_long nonblocking = 1;
    char    transbuf[1000] ;//這個地方的數據大小,只是跟填充網絡發送緩衝區有關
    char    IPADDR[17];
    memset(transbuf,'a',sizeof(transbuf));

    WSAStartup(0x202,&wsaData);
    sSend = socket(AF_INET, SOCK_DGRAM,0);
    //設置爲非阻塞模式
    ioctlsocket(sSend,FIONBIO,&nonblocking);//在非阻塞模式下,udp發送基本不佔用時間,並且跟ip地址無關係
    setsockopt(sSend,SOL_SOCKET,SO_SNDTIMEO, (char*)&lngSendTimeOut,sizeof(lngSendTimeOut) );
    setsockopt(sSend,SOL_SOCKET,SO_RCVTIMEO,(char*)&lngRecvTimeOut,sizeof(lngRecvTimeOut) ); 
    sockObject.sin_port = htons(3500);
    sockObject.sin_family = AF_INET;
    for(int i = 1;i < 35; i++)
    {
        sprintf(IPADDR,"192.168.0.1%d",i);
        LastTime = GetTickCount();
        addr = inet_addr((char *)IPADDR);
        memcpy(&sockObject.sin_addr,&addr,sizeof(addr));
        //這個地方的耗時跟兩個因素有關係
        //官方:
        //If no buffer space is available within the transport system to hold the data to be transmitted, 
        //sendto will block unless the socket has been placed in a nonblocking mode. 
        //也就是說,對於sendto函數,他的發送返回成功並不表明網絡發送了,他只是將數據發送到傳輸層的緩衝區,就返回結果
        //而對於阻塞的socket,當這個ip地址即便不存在,但緩衝區未滿的狀況下,他也是返回成功的,並且基本不耗時,
        //但當緩衝區滿了之後,sendto就會阻塞,這個時候會產生耗時
        //對於非阻塞的socket,緩衝區未滿的時候,它基本不佔發送時間,滿了,sendto也會當即返回結果,整個過程基本不耗時

        wrc = sendto(sSend,transbuf,sizeof(transbuf),0,(struct sockaddr *)&sockObject,sizeof(sockObject));    
        Curtime = GetTickCount();
        EscpTime = Curtime - LastTime;
        if (wrc != SOCKET_ERROR) 
        {
            printf("Send Some Data To %s,Use Time:%d ms\n",IPADDR,EscpTime);
            //    Sleep(1000);
        }
        else 
        {
            printf("*Send Some Data To %s,failed ,Use Time:%d ms,sendto return value:0x%x\n",IPADDR,EscpTime,wrc);
        }
        Sleep(1);

    }
    closesocket(sSend);
    WSACleanup();
    return 0;
}

 

 

 

上面是我測試的時候的一個源碼。學習

 

而後我在srs論壇裏面也跟羣友諮詢了這個問題,他的拷貝了一個官方的解釋給我:測試

If no buffer space is available within the transport system to hold the data to be transmitted, sendto will block unless the socket has been placed in a nonblocking mode. spa

直接翻譯過來的意思爲:.net

若是沒有可用的緩衝區空間運輸系統內的數據傳輸、sendto將阻止,除非socket被放置在一個非阻塞模式。

 

而後我在源碼裏面也進行註釋:

udp 的sendto函數,其實他只是將發生的數據包進行了一次拷貝,拷貝到了傳輸層的網絡緩衝區,而後函數返回結果。因此sendto函數的返回值並不能表明網絡真實的一個發送狀況結果。既然理解了上面的這個,因此udp的sendto耗時基本能夠忽略了。由於數據拷貝基本不佔用多大實際時間。但對於阻塞的socket,當網絡緩衝區滿了之後,sendto就會阻塞。而對於非阻塞的socket,即便網絡緩衝區滿了,他也會當即返回,不會進行阻塞等待,因此這種狀況下適合於流媒體發送數據,即便單線程做戰分發也是能夠的。

相關文章
相關標籤/搜索