原文轉自:http://hi.baidu.com/doodlezone/item/74a203155efe26dbbf9042dd
UDT文檔閱讀理解
一、 概述
UDT是一個高性能的基於UDP的數據傳輸協議,它是為支持高速廣域網上海量數據傳輸而設計,為解決TCP的效率和公平問題,同時提供可靠的數據流和報文傳輸。
UDT是C++庫,幾乎類同於BSD socket APIs。
UDT是多線程安全的,但並不是多進程共享。
二、 原理
UDT有兩種傳輸模式:數據流模式(SOCK_STREAM)和數據報模式(SOCK_DGRAM)
數據流模式類似於傳統的BSD套接字,這種模式下不能保證任何一端一個調用就把所有的數據發送了,因為在數據流中沒有邊界信息,進程需用loop來發送和接收。
數據報模式會將數據作為整個單元來傳送,不需要循環來接收和發送數據,要么全部發送,要么一點也不發送。在接收端如果緩沖區不夠大,則只會接收到部分數據,其他的將被丟棄。
UDT發送數據有阻塞與非阻塞方式,在阻塞方式下,會直到把需要發送的數據發送完再返回,而非阻塞方式下,會根據socket底層的可用緩沖的大小,將緩沖區中的數據拷貝過去,有多大緩沖就拷貝多少,緩沖區滿了就立即返回,這個時候的返回值只是拷貝了多少,不代表發送了多少,同時剩下的部分需要再次調用send
UDT增加了rendezvous模式,這是一種連接模式,用來穿透防火牆。這種模式下,UDT不能調用listen和accept,而是兩端bind后同時建立連接。
UDT允許用戶自己定義擁塞控制。可以繼承DUT/CCC下的CCC類來改變一些變量,如擁塞窗口,./app/cc.h下的實例是學習的快速途徑。
三、 安裝及平台
UDT是基於源碼的庫,所以沒有安裝文件工具,我們只需要根據不同的系統和CPU架構使用命令來make相應的庫即可。
UDT支持的系統:Linux,BSD,OSX
UDT支持的架構:IA32,IA64,POWERPC,AMD64
命令: make –e os=XXX arch=XXX
UDT來源於BSD socket API只有一個頭文件<udt.h>,一些繼續使用BSDAPI 另一些需要加標示符UDT::
庫:libudt.h udt.dll udt.dylib libudt.a udt.lib
四、 配置設置
讀取和設置選項通過getsockopt和setsockopt方法,一般不要修改默認選項除非應用不能正常運行。
UDT_MSS用來設置包的大小,一般情況下最佳的UDT包的大小是網絡MTU(默認1500字節)的大小,連接的兩端都要設置這個值,傳輸時取兩端的較小者。
UDT用不同的同步方式語義UDT_SNDSYN和UDT_RCVSYN,它可以獨立的設置發送和接收同步,具有更多的靈活性。它不允許在連接建立和關閉的時候進行非阻塞操作。
UDT緩沖區的大小理論上越大越好,要運行的好兩端buffer至少為【帶寬*RTT】
UDT使用UDP數據通道,所以UDP緩沖大小影響程序運行,但隨着buffer變大效果也會越來越不明顯。一般來說發送端的buffer小一點,因為包的發送沒有限制太多,但太大會增加端到端的延時。
UDT_LINGER是設置socket關閉時是否立即停止發送緩沖區的數據。
UDT_RENDEZVOUS設置集合點模式,在穿越防火牆時很有用。
UDT_SNDTIMEO和UDT_RCVTIMEO是timeout值
UDT_REUSEADDR設置UDP端口是否可以給其他UDT使用,默認值是true。
以下情況需設置false
1,兩個UDT socket不能在同一端口監聽。
2,兩個UDT socket綁定在同一IP同一端口而不能建立連接。
發送發有兩種選擇:
1,TTL(默認無限)為timeout時間。
2,消息有序到達,直到上一個消息到達或被丟棄才發下一個。
UDT提供文件傳輸,UDT::sendfile和UDT::recvfile這種發送接收方式跟
UDT::send和UDT::recv是正交的。也就是說用sendfile發送不一定要用recvfile接收。另外,sendfile和recvfile不受SNDSYN,RCVSYN,SNDTIMEO,RCVTIMEO影響。它使用C++ fstream進行文件IO。
UDT打洞,在傳統方式下,穿越防火牆時是用SO_REUSEADDR選項去打開兩個socket綁定同一個端口,一個監聽一個建立連接。而UDT提供直接相連的方式。
UDT允許一個進程中的所有socket綁定到同一端口但只允許一個監聽。
UDT允許綁定已經存在的UDP端口有兩個好處:
1,當應用程序向服務器發送一個空包去獲得它的地址(尤其是在NAT防火牆下)時,用戶會創建一個UDP包發送個server確定綁定的端口,然后UDP端口可以順便給UDT使用。
2,一些本地防火牆在關閉“打洞”時會改變映射端口,新的UDT綁定的端口將失效,此時用UDP的是必須的。
錯誤處理:所有的UDT API在遇到錯誤時都會返回error UDT定義兩種錯誤,
UDT::INVALID_SOCK和UDT::ERROR。可以用getErrorCode和getErrorMessage方法查看存放在ERRORINFO數據結構中的錯誤代碼及信息。
成功的調用不會清楚錯誤,所以應用程序應該利用返回值檢查調用結果,可以調用個體lasterror().clean()來清除錯誤日志。