亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

網(wǎng)絡(luò)協(xié)議及編碼

fizz / 2780人閱讀

摘要:協(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ò)。

自定義協(xié)議實(shí)例: 1、基于文本的編碼方式
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

相關(guān)文章

  • 以太坊連載(二):如何使用Homestead文檔以太坊路線圖

    摘要:以太坊的使用基礎(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)選擇什么樣的客戶端給出...

    fireflow 評(píng)論0 收藏0
  • 造輪子系列(二): 史上最簡(jiǎn)單的長連接通信協(xié)議實(shí)現(xiàn)

    摘要:背景現(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í)代, 后端大哥們于是分分鐘就能造一...

    Alliot 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<