摘要:協(xié)議族協(xié)議協(xié)議協(xié)議應(yīng)用程序通過套接字對(duì)協(xié)議和協(xié)議所提供的服務(wù)進(jìn)行訪問。網(wǎng)絡(luò)層完成將分組報(bào)文傳輸?shù)剿哪康牡?,即路由功能,一般采用協(xié)議。程序間達(dá)成的這種包含了信息交換的形式和意義的共識(shí)稱為協(xié)議。
TCP/IP協(xié)議族:IP協(xié)議、TCP協(xié)議、UDP協(xié)議
應(yīng)用程序通過套接字API對(duì)UPD協(xié)議和TCP協(xié)議所提供的服務(wù)進(jìn)行訪問。
底層由物理層:基礎(chǔ)的通信信道構(gòu)成,如以太網(wǎng)/WIFI或調(diào)制解調(diào)器撥號(hào)連接。
網(wǎng)絡(luò)層:完成將分組報(bào)文(packet)傳輸?shù)剿哪康牡?,即路由功能,一般采用IP協(xié)議。IP協(xié)議提供了一種數(shù)據(jù)服務(wù):每組分組報(bào)文都有網(wǎng)絡(luò)獨(dú)立處理和分發(fā),就像信件或包裹通過郵政系統(tǒng)發(fā)送一樣。每個(gè)IP報(bào)文必須包含一個(gè)保存其目的地址的字段。
傳輸層:提供了TCP協(xié)議和UDP協(xié)議,這兩種協(xié)議都建立在IP層提供的服務(wù)之上,IP協(xié)議只是將分組報(bào)文分發(fā)到不同的主機(jī),然后還需要更細(xì)粒度的尋址將報(bào)文發(fā)送到主機(jī)指定的應(yīng)用程序端口,這個(gè)尋址功能是TCP或UDP要完成的,因此他們也成為端到端的傳輸協(xié)議。IP協(xié)議只是將數(shù)據(jù)從一個(gè)主機(jī)傳到另一個(gè)主機(jī)。
TCP協(xié)議提供一個(gè)可信賴的字節(jié)流信道(處理報(bào)文丟失、重傳及順序混亂問題),一種面向連接的協(xié)議:在使用它進(jìn)行通信之前,兩個(gè)應(yīng)用程序之間首先要建立一個(gè)TCP連接,這涉及到兩臺(tái)機(jī)器的TCP部件完成握手消息的交互。
UDP協(xié)議不嘗試對(duì)IP層產(chǎn)生的錯(cuò)誤進(jìn)行修復(fù),僅僅是簡(jiǎn)單地?cái)U(kuò)展IP協(xié)議,傳輸?shù)蕉丝凇?/p>
網(wǎng)絡(luò)層中的IP協(xié)議就像把郵件送到某個(gè)街道的某個(gè)樓的信箱,而傳輸層則是將信件送到該樓層的具體某個(gè)房間里頭。
IP協(xié)議其實(shí)是單播協(xié)議,還有多播協(xié)議,廣播到任意數(shù)量的地址。
什么是套接字(Socket)一種抽象層,應(yīng)用程序通過它來發(fā)送和接受數(shù)據(jù),就像應(yīng)用程序打開一個(gè)文件句柄,將數(shù)據(jù)讀寫到穩(wěn)定的存儲(chǔ)器上一樣。使用socket可以將應(yīng)用程序添加到網(wǎng)絡(luò)中,并與處于同一個(gè)網(wǎng)絡(luò)中的其他應(yīng)用程序進(jìn)行通信。一臺(tái)計(jì)算機(jī)上的應(yīng)用程序向socket寫入的信息能夠被另一臺(tái)計(jì)算機(jī)上的另一個(gè)應(yīng)用程序讀取。
不同類型的socket與不同類型的底層協(xié)議族以及同一個(gè)協(xié)議族的不同協(xié)議棧相關(guān)聯(lián)。
TCP/IP協(xié)議族中的主要socket類型為流套接字(stream scoket)和數(shù)據(jù)報(bào)套接字(datagram socket)。
流套接字將TCP作為其端對(duì)端協(xié)議,提供了一個(gè)可信賴的字節(jié)流服務(wù)。
數(shù)據(jù)報(bào)套接字使用UDP協(xié)議,提供了一個(gè)best-effort的數(shù)據(jù)報(bào)服務(wù)。
一個(gè)套接字抽象層可以被多個(gè)應(yīng)用程序引用,每個(gè)使用了特定套接字的程序都可以通過那個(gè)套接字進(jìn)行通信。每個(gè)端口都標(biāo)識(shí)了一臺(tái)主機(jī)上的一個(gè)應(yīng)用程序。實(shí)際上,一個(gè)端口確定了一臺(tái)主機(jī)上的一個(gè)套接字。
任何要交換信息的程序之間在信息的編碼方式上必須達(dá)成共識(shí)(比如將信息表示為位序列),以及哪個(gè)程序發(fā)送消息,什么時(shí)候和怎么接受信息都將影響程序的行為。程序間達(dá)成的這種包含了信息交換的形式和意義的共識(shí)稱為協(xié)議。用來實(shí)現(xiàn)特定應(yīng)用程序的協(xié)議稱為應(yīng)用程序協(xié)議。
TCP/IP協(xié)議的唯一約束是,信息必須在塊(chunk)中發(fā)送和接收,而塊的長度必須是8位的倍數(shù),因此我們可以認(rèn)為TCP/IP協(xié)議中傳輸?shù)男畔⑹亲止?jié)序列。
如果是自己設(shè)計(jì)和編寫套接字的客戶端和服務(wù)器端,則可以隨心所欲地定義自己的應(yīng)用程序協(xié)議。
對(duì)于需要超過一個(gè)字節(jié)來表示的數(shù)據(jù)類型,我們必須知道這些字節(jié)的發(fā)送順序。
一種是從整數(shù)的右邊開始,由低位到高位發(fā)送,即little-endian順序;一種是從左邊開始,由高位到低位發(fā)送,即big-endian順序。
對(duì)于任何多字節(jié)的整數(shù),發(fā)送者和接收者必須在使用big-endian順序還是使用little-endian順序上達(dá)成共識(shí)。
另外一個(gè)需要達(dá)成的共識(shí)是:所傳輸?shù)臄?shù)值是有符號(hào)的還是無符號(hào)的。
對(duì)于給定的k位,我們可以通過二進(jìn)制補(bǔ)碼來表示-2的k-1次方到2的k-1次方-1范圍的值,如果使用無符號(hào),則可以表示0到2的k次方-1之間的數(shù)值。
DataOutputStream允許你將基本數(shù)據(jù)類型按big-endian順序進(jìn)行編碼,即將整數(shù)以適當(dāng)大小的二進(jìn)制補(bǔ)碼的形式寫到流中。
在一組符號(hào)與一組整數(shù)之間的映射稱為編碼字符集,比如ASCII(將英文字母、數(shù)字、標(biāo)點(diǎn)符號(hào)以及一些特殊符號(hào)映射為0-127的整數(shù)),Unicode(映射到0~65535之間的的整數(shù))。
編碼方案:發(fā)送者和接收者需要對(duì)這些整數(shù)如何表示成字節(jié)序列達(dá)成一致。
字符集:charset,由編碼字符集和字符的編碼方法結(jié)合起來。
Java的輸入輸出流Java里頭內(nèi)置了特定的序列化,隱藏了所有繁瑣的參數(shù)編碼解碼細(xì)節(jié)。Serialization處理了將實(shí)際的Java對(duì)象轉(zhuǎn)換成字節(jié)序列的工作,因此你可以在不同虛擬機(jī)之間傳遞Java對(duì)象實(shí)例。
缺點(diǎn)是:它們比較籠統(tǒng),在通信開銷上不能做到最高效,比如一個(gè)對(duì)象的序列化形式其包含的信息在JVM環(huán)境以外是毫無意義的;其次是Serializable和Externalizable接口不能用于已經(jīng)定義了不同傳輸格式的情況;最后用戶自定義的類必須自己實(shí)現(xiàn)序列化接口,容易出錯(cuò)。
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; }
文本方式通常使用一個(gè)魔數(shù)來開頭。
2、基于二進(jìn)制的編碼方式二進(jìn)制格式使用固定大小的消息,每條消息由一個(gè)特殊字節(jié)開始(魔數(shù))。
/* 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協(xié)議是一個(gè)基于流的服務(wù),因而需要提供字節(jié)的幀。
// 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); 這里采用了基于顯示長度的方式來標(biāo)識(shí)幀大小:LengthFarmer類為每條消息添加一個(gè)長度前綴。 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(); }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/65889.html
摘要:以太坊的使用基礎(chǔ)指南通過本節(jié)可以獲取用戶參與到以太坊項(xiàng)目中的基本方法。的發(fā)布是以太坊平臺(tái)的第二個(gè)主要版本,也是以太坊發(fā)布的第一個(gè)正式版本。硬分叉變更以太坊從狹義上來說,是一系列協(xié)議。 以太坊的使用:基礎(chǔ)指南通過本節(jié)可以獲取用戶參與到以太坊項(xiàng)目中的基本方法。首先,要想成為網(wǎng)絡(luò)中的節(jié)點(diǎn),需要運(yùn)行一個(gè)以太坊客戶端。在選擇客戶端這一節(jié)中列出了多重實(shí)現(xiàn),同時(shí)針對(duì)不同的安裝應(yīng)選擇什么樣的客戶端給出...
摘要:背景現(xiàn)在寫客戶端或者網(wǎng)頁的時(shí)候越來越多的需要與長連接打交道尤其是在這個(gè)老板動(dòng)不動(dòng)就要搞一個(gè)聊天系統(tǒng)的時(shí)代后端大哥們于是分分鐘就能造一個(gè)基于或者的消息協(xié)議出來但是問題在于每做一個(gè)新項(xiàng)目后端大哥們就能造出一個(gè)新協(xié)議而且能有各種神奇的限制比如說要 背景 現(xiàn)在寫客戶端或者網(wǎng)頁的時(shí)候, 越來越多的需要與長連接打交道, 尤其是在這個(gè)老板動(dòng)不動(dòng)就要搞一個(gè)聊天系統(tǒng)的時(shí)代, 后端大哥們于是分分鐘就能造一...
閱讀 1035·2019-08-30 14:24
閱讀 1176·2019-08-30 14:13
閱讀 1895·2019-08-29 17:21
閱讀 2874·2019-08-29 13:44
閱讀 1756·2019-08-29 11:04
閱讀 552·2019-08-26 10:44
閱讀 2665·2019-08-23 14:04
閱讀 994·2019-08-23 12:08