轉載請註明出處:http://www.cnblogs.com/lihaiping/p/6811791.htmlhtml
本學習筆記,僅用於問題探討,若有不一樣,能夠討論。服務器
最近在看流媒體分發服務器的相關代碼,其中對於網絡udp數據發送耗時的研究,這塊有一點點疑問:網絡
udp的sendto發送數據的耗時大概爲多少?他的耗時跟發送的數據包大小有沒有關係?跟對端的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,即便網絡緩衝區滿了,他也會當即返回,不會進行阻塞等待,因此這種狀況下適合於流媒體發送數據,即便單線程做戰分發也是能夠的。