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


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

本學習筆記,僅用於問題探討,如有不同,可以討論。

 

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

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

 

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

 

然后我拷貝了論壇的測試程序,在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. 

直接翻譯過來的意思為:

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

 

然后我在源碼里面也進行注釋:

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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM