摘要:協議族協議協議協議應用程序通過套接字對協議和協議所提供的服務進行訪問。網絡層完成將分組報文傳輸到它的目的地,即路由功能,一般采用協議。程序間達成的這種包含了信息交換的形式和意義的共識稱為協議。
TCP/IP協議族:IP協議、TCP協議、UDP協議
應用程序通過套接字API對UPD協議和TCP協議所提供的服務進行訪問。
底層由物理層:基礎的通信信道構成,如以太網/WIFI或調制解調器撥號連接。
網絡層:完成將分組報文(packet)傳輸到它的目的地,即路由功能,一般采用IP協議。IP協議提供了一種數據服務:每組分組報文都有網絡獨立處理和分發,就像信件或包裹通過郵政系統發送一樣。每個IP報文必須包含一個保存其目的地址的字段。
傳輸層:提供了TCP協議和UDP協議,這兩種協議都建立在IP層提供的服務之上,IP協議只是將分組報文分發到不同的主機,然后還需要更細粒度的尋址將報文發送到主機指定的應用程序端口,這個尋址功能是TCP或UDP要完成的,因此他們也成為端到端的傳輸協議。IP協議只是將數據從一個主機傳到另一個主機。
TCP協議提供一個可信賴的字節流信道(處理報文丟失、重傳及順序混亂問題),一種面向連接的協議:在使用它進行通信之前,兩個應用程序之間首先要建立一個TCP連接,這涉及到兩臺機器的TCP部件完成握手消息的交互。
UDP協議不嘗試對IP層產生的錯誤進行修復,僅僅是簡單地擴展IP協議,傳輸到端口。
網絡層中的IP協議就像把郵件送到某個街道的某個樓的信箱,而傳輸層則是將信件送到該樓層的具體某個房間里頭。
IP協議其實是單播協議,還有多播協議,廣播到任意數量的地址。
什么是套接字(Socket)一種抽象層,應用程序通過它來發送和接受數據,就像應用程序打開一個文件句柄,將數據讀寫到穩定的存儲器上一樣。使用socket可以將應用程序添加到網絡中,并與處于同一個網絡中的其他應用程序進行通信。一臺計算機上的應用程序向socket寫入的信息能夠被另一臺計算機上的另一個應用程序讀取。
不同類型的socket與不同類型的底層協議族以及同一個協議族的不同協議棧相關聯。
TCP/IP協議族中的主要socket類型為流套接字(stream scoket)和數據報套接字(datagram socket)。
流套接字將TCP作為其端對端協議,提供了一個可信賴的字節流服務。
數據報套接字使用UDP協議,提供了一個best-effort的數據報服務。
一個套接字抽象層可以被多個應用程序引用,每個使用了特定套接字的程序都可以通過那個套接字進行通信。每個端口都標識了一臺主機上的一個應用程序。實際上,一個端口確定了一臺主機上的一個套接字。
任何要交換信息的程序之間在信息的編碼方式上必須達成共識(比如將信息表示為位序列),以及哪個程序發送消息,什么時候和怎么接受信息都將影響程序的行為。程序間達成的這種包含了信息交換的形式和意義的共識稱為協議。用來實現特定應用程序的協議稱為應用程序協議。
TCP/IP協議的唯一約束是,信息必須在塊(chunk)中發送和接收,而塊的長度必須是8位的倍數,因此我們可以認為TCP/IP協議中傳輸的信息是字節序列。
如果是自己設計和編寫套接字的客戶端和服務器端,則可以隨心所欲地定義自己的應用程序協議。
對于需要超過一個字節來表示的數據類型,我們必須知道這些字節的發送順序。
一種是從整數的右邊開始,由低位到高位發送,即little-endian順序;一種是從左邊開始,由高位到低位發送,即big-endian順序。
對于任何多字節的整數,發送者和接收者必須在使用big-endian順序還是使用little-endian順序上達成共識。
另外一個需要達成的共識是:所傳輸的數值是有符號的還是無符號的。
對于給定的k位,我們可以通過二進制補碼來表示-2的k-1次方到2的k-1次方-1范圍的值,如果使用無符號,則可以表示0到2的k次方-1之間的數值。
DataOutputStream允許你將基本數據類型按big-endian順序進行編碼,即將整數以適當大小的二進制補碼的形式寫到流中。
在一組符號與一組整數之間的映射稱為編碼字符集,比如ASCII(將英文字母、數字、標點符號以及一些特殊符號映射為0-127的整數),Unicode(映射到0~65535之間的的整數)。
編碼方案:發送者和接收者需要對這些整數如何表示成字節序列達成一致。
字符集:charset,由編碼字符集和字符的編碼方法結合起來。
Java的輸入輸出流Java里頭內置了特定的序列化,隱藏了所有繁瑣的參數編碼解碼細節。Serialization處理了將實際的Java對象轉換成字節序列的工作,因此你可以在不同虛擬機之間傳遞Java對象實例。
缺點是:它們比較籠統,在通信開銷上不能做到最高效,比如一個對象的序列化形式其包含的信息在JVM環境以外是毫無意義的;其次是Serializable和Externalizable接口不能用于已經定義了不同傳輸格式的情況;最后用戶自定義的類必須自己實現序列化接口,容易出錯。
public byte[] toWire(VoteMsg msg) throws IOException { String msgString = MAGIC + DELIMSTR + (msg.isInquiry() ? INQSTR : VOTESTR) + DELIMSTR + (msg.isResponse() ? RESPONSESTR + DELIMSTR : "") + Integer.toString(msg.getCandidateID()) + DELIMSTR + Long.toString(msg.getVoteCount()); byte data[] = msgString.getBytes(CHARSETNAME); return data; }
文本方式通常使用一個魔數來開頭。
2、基于二進制的編碼方式二進制格式使用固定大小的消息,每條消息由一個特殊字節開始(魔數)。
/* Wire Format * 1 1 1 1 1 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | Magic |Flags| ZERO | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | Candidate ID | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | | * | Vote Count (only in response) | * | | * | | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ public byte[] toWire(VoteMsg msg) throws IOException { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(byteStream); // converts ints short magicAndFlags = MAGIC; if (msg.isInquiry()) { magicAndFlags |= INQUIRE_FLAG; } if (msg.isResponse()) { magicAndFlags |= RESPONSE_FLAG; } out.writeShort(magicAndFlags); // We know the candidate ID will fit in a short: it"s > 0 && < 1000 out.writeShort((short) msg.getCandidateID()); if (msg.isResponse()) { out.writeLong(msg.getVoteCount()); } out.flush(); byte[] data = byteStream.toByteArray(); return data; }
TCP協議是一個基于流的服務,因而需要提供字節的幀。
// Create an inquiry request (2nd arg = true) VoteMsg msg = new VoteMsg(false, true, CANDIDATEID, 0); byte[] encodedMsg = coder.toWire(msg); // Send request System.out.println("Sending Inquiry (" + encodedMsg.length + " bytes): "); System.out.println(msg); framer.frameMsg(encodedMsg, out); 這里采用了基于顯示長度的方式來標識幀大小:LengthFarmer類為每條消息添加一個長度前綴。 public void frameMsg(byte[] message, OutputStream out) throws IOException { if (message.length > MAXMESSAGELENGTH) { throw new IOException("message too long"); } // write length prefix out.write((message.length >> BYTESHIFT) & BYTEMASK); out.write(message.length & BYTEMASK); // write message out.write(message); out.flush(); }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65889.html
摘要:以太坊的使用基礎指南通過本節可以獲取用戶參與到以太坊項目中的基本方法。的發布是以太坊平臺的第二個主要版本,也是以太坊發布的第一個正式版本。硬分叉變更以太坊從狹義上來說,是一系列協議。 以太坊的使用:基礎指南通過本節可以獲取用戶參與到以太坊項目中的基本方法。首先,要想成為網絡中的節點,需要運行一個以太坊客戶端。在選擇客戶端這一節中列出了多重實現,同時針對不同的安裝應選擇什么樣的客戶端給出...
摘要:背景現在寫客戶端或者網頁的時候越來越多的需要與長連接打交道尤其是在這個老板動不動就要搞一個聊天系統的時代后端大哥們于是分分鐘就能造一個基于或者的消息協議出來但是問題在于每做一個新項目后端大哥們就能造出一個新協議而且能有各種神奇的限制比如說要 背景 現在寫客戶端或者網頁的時候, 越來越多的需要與長連接打交道, 尤其是在這個老板動不動就要搞一個聊天系統的時代, 后端大哥們于是分分鐘就能造一...
閱讀 955·2019-08-30 14:24
閱讀 987·2019-08-30 14:13
閱讀 1799·2019-08-29 17:21
閱讀 2661·2019-08-29 13:44
閱讀 1654·2019-08-29 11:04
閱讀 438·2019-08-26 10:44
閱讀 2564·2019-08-23 14:04
閱讀 908·2019-08-23 12:08