哪些方法可以提高socket的傳輸效率?
Socket的傳輸效率不同的I/O模型效率千差萬別,首先介紹一下unix的5種I/O模型,分別是:
1.阻塞I/O
在進程空間中調用recvfrom,其系統調用直到數據包到達且被復制到應用程序的緩沖區或者發生錯誤才返回,在此期間進程 進入睡眠或者掛起狀態。(進程掛起了)
2.非阻塞I/O
非阻塞I/O模型:recvfrom從應用層到內核的時候,如果該緩沖區沒有數據的話,就直接返回一個ewouldblock錯誤,用戶進程便在成功返回數據之前一直在調用recv操作詢問數據可讀性,輪詢的操作方式。(輪詢占用CPU)
3.I/O復用
I/O復用(select,poll,epoll等支持I/O多路復用):進程通過將一個或多個連接傳遞給select或poll系統調用,I/O復用實現了多個連接或者多種連接(TCP,UDP等)共用了同一種等待機制,select會返回某個連接的可讀條件,調用recv/recvfrom把所讀的數據報拷貝到應用進程的緩沖區中。(多個連接注冊同一個select,nio是基于I/O復用模型實現的)
4.信號驅動I/O
通過sigaction系統調用實現了SIGIO信號的捕獲與處理函數,它是非阻塞的。當有數據準備就緒時,就為該進程生成一個SIGIO信號,通過信號回調通知應用程序調用recvfrom來讀取數據。(捕獲內核發送過來的信號)
5.異步I/O
異步I/O:告知內核啟動某個操作,并讓內核在整個操作完成后通知我們,包括將數據從內核拷貝到用戶空間(異步的)。
前面四種情況都是同步的,最后一種是異步;已java為例對應的api有ServerSocket,ServerSocketChannel,AsynchronousServerSocketChannel;
我覺得可以從以下幾個方面著手:
1.選擇合適的I/O模型
2.線程模型
3.高效的協議
1.選擇合適的I/O模型
如上介紹的五種I/O模型,不同的I/O模型效率千差萬別;比如早期的網絡連接使用阻塞的方式,然后每個請求對應一個線程的方式,到現在普遍使用的多路復用模式,使用很小的線程可以處理大量的連接
2.線程模型
有對應的單線程模型,多線程模型,主從線程模型;主從線程模型現在在很多通信框架中普遍使用,大致就是連接的建立和讀寫分成多個線程池來處理;
3.高效的協議
既然是基于socket傳輸數據,那必然需要在其基礎上設計合適的協議,比如說我們常用的協議格式如下:
協議{協議頭(header)協議數據(data)}另外在協議的基礎上我們往往需要對數據進行序列化處理,不同的序列化方式性能上也差距很大,比如protobuf在性能上和數據量上都有優秀;當然往往也需要用到壓縮格式,不同的壓縮方法性能上也差距很大;
總結
本文從三個方面介紹了如何提高socket的傳輸效率;當然除了以上說的幾種情況,也和一些外部環境的配置有關,比如服務器的連接數設置,網絡帶寬等等