簡單的文本協議、二進制協議

寫網絡程序躲不過協議,協議其實就是定義了消息的格式,以及消息是如何交換的。協議可簡單可複雜,複雜精密如TCP協議,簡單奔放如HTTP的協議。這裏將我所接觸到的協議稍微總結一下,最後拋出一個我的設計的簡單通用的文本協議。mysql

設計一個協議不是一件很容易的事情,尤爲是當對設計的要求包含很好的描述性和可擴展性的時候。若是再將效率考慮在內,則更是件耗腦力的活。在繼續討論下去以前,先看看現有的一些協議吧。這裏主要討論的是應用層的協議,應用層的協議大可能是請求響應模式(除了zeromq這個變態的傢伙,後面再說),因此這裏側重討論消息格式。git

HTTP協議github

這多是你們接觸得最多的協議了,HTTP協議是一個比較簡單的基於文本的協議。消息格式基於文本,換行分隔鍵值串,鍵和值用冒號分隔,同時定義了一些標準的鍵和值。這個協議描述性教強——人類可讀。擴展性強——加自定義的頭很容易,也幾乎不會有反作用(除了消息體積增長一點點)。可是,缺點就是標準定義的東西太多了,細節太多。解析較複雜。redis

memcached協議sql

memcached有兩種協議,文本協議二進制協議,文本協議以換行表示一個請求結束。請求內部參數以空格分隔。爲了二進制安全,在二進制數據前要加上長度這個參數,如set x 3 abc\r\n。安全

文本協議當然簡單,但是當請求很小的時候,過多的協議自己的數據則顯得浪費(好比每一個HTTP請求只發送一個字母,可HTTP頭可能有上百的字符,太浪費了),並且,server在接收到請求以後還要作文本解析,也耗cpu,因而memcached又推出了二進制協議,爲了錦上添花,是的memcached更加高效。二進制協議的優勢就是高效,由於全部信息都以最少的數據量來表達,且server解析請求時作的是數學比較而不是字符串比較,效率高不少。網絡

memcached的協議比起HTTP來就輕得多了(固然,二者所面向的場景不同,故這個比較沒太大意義)。可是,也有缺點,就是擴展性較差,協議定得比較死,哪一個位置上有哪些東西,是什麼意義是定死的。因此,直接哪來用在不一樣的場景下不大現實。memcached

redis協議google

redis的協議也是文本協議,可是設計得比較當心和通用(我後面本身定義的協議深受其影響),在保證描述性的同時儘可能減小協議自己的數據量,好比,在memcached的文本協議中,錯誤用「ERROR\r\n」來表示,而redis使用「-」來表示,用「:」開頭的行表示整數等等。這樣的設計結合了文本協議的簡單和一部分二進制協議的高效。用在redis這個場合,非常適合。交換方式一樣是請求響應。redis協議有一個缺點,就是,一個消息有多少參數是須要在開頭指定的。不像HTTP協議用空行來表示結束。這就帶來一個缺點,很差流水操做,也就是說消息必須在發送第一個字節以前被徹底肯定,由於第一個東西就是參數個數:-(。spa

上面討論的基本都是文本協議,固然還有不少採用二進制協議的服務,如gearman、mysql等,二進制協議就至關於壓縮版的文本協議,提升了傳輸效率,可是下降了描述性和靈活性(萬一那個位置預留的位數不夠就囧了)。

總的來講,這就是一個平衡的過程。若是消息體不是很小(好比每次只傳一個字節的消息就很小了),那麼採用文本協議仍是值得的。畢竟文本協議簡單,好擴展,利於調試(telnet就能夠當客戶端用),雖然說消息是讓計算機讀的,但有時候也要人去看。因此,能用文本仍是用文本吧。

簡單文本協議

最後我定義了一個簡單的基於文本的協議,叫作simpletp(Simple Text based Protocol),詳細定義在這裏http://simpletp.org,這個協議是爲了簡單的RPC而設計,結合了HTTP協議的靈活(以空行結束),redis協議的輕量(size+data)。但爲了簡單通用,沒有采用redis的單字符表示類型的設計,由於這樣就會引入額外的複雜性,如表示整數用「:」,那麼浮點數、複數等等怎麼辦,乾脆什麼類型都沒有,就簡單的傳輸size+data串(有點相似zeromq,可是比zeromq作的事情少),而具體的類型則交由其餘機制去處理,如protocol buffer。

相關文章
相關標籤/搜索