<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                # Swoole編程指南-固定包頭協議 [原文鏈接](http://www.catplanet.me/?id=13) [TOC] ## 什么是固定包頭協議 固定包頭協議是在需要發送的數據前,加上一段預先規約好長度和格式的數據體,在該數據體中存放有后續數據的相應信息(一般情況下,后續數據的長度字段是必填項)的協議,這樣一段數據體則稱之為協議包頭。在TCP的數據流中,使用固定包頭協議的數據流特征如下: > | len長度 | 數據 | len長度 | 數據 | ## 知識科普:字節序 這里需要說明一下字節序的問題。在內存中,一個整數由四個連續的字節序列表示。例如一個int類型的變量x,其內存地址為0x100,那么這個變量的四個字節會被存儲在0x100,0x101,0x102,0x103。 字節序則決定了這個變量的內容在這四個地址中的存放順序。通常根據字節排列順序的不同,將字節序區分為大端字節序和小端字節序。這里假設該變量x的16進制表示為0x12345678,在大端字節序中,該變量將以如下形式存放在內存中: ... 0x100 0x101 0x102 0x103 ... ... 12 34 56 78 ... 而在小端字節序中,則以如下形式存放: ... 0x100 0x101 0x102 0x103 ... ... 78 56 34 12 ... 可以看到,以內存地址從小到大代表從低到高,并且將變量從左到右設定為從低到高,大端序列就是高位字節存放在高位,低位字節存放在低位,而小端序反之。 在機器中,使用大端序和小端序完全取決于硬件本身。因此,在不同的機器之間通信時,需要有一個統一的字節序來進行傳輸,由此誕生了網絡字節序的概念。網絡字節序一般采用大端序(IP協議指定),而機器字節序則由機器本身決定。兩者之間需要借助系統函數進行轉換。 ## 開啟協議檢測 在Swoole中,可以使用如下配置選項來開啟固定包頭協議功能: ``` $server->set([ 'open_length_check' => 1, // 開啟協議解析 'package_length_type' => 'N', // 長度字段的類型 'package_length_offset' => 0, //第N個字節是包長度的值 'package_body_offset' => 4, //第N個字節開始計算長度 'package_max_length' => 2000000, //協議最大長度 ]); ``` 在這里,package_length_type規定了length長度字段的類型,這個類型等價于使用PHP的pack函數打包數據時使用的類型,具體類型如下表所示: | 類型 | 長度 | 說明 | 范圍 | | --- | --- | --- | --- | | c | 1字節 | 有符號Char | -128 ~ 127 | | C | 1字節 | 無符號Char | 0 ~ 256 | | s | 2字節 | 有符號,機器字節序 | -32768 ~ 32767| | S | 2字節 | 無符號,機器字節序 | 0 ~ 65535| | n | 2字節 | 無符號,網絡字節序 | 0 ~ 65535| | N | 4字節 | 無符號,網絡字節序 | 0 ~ 4294967295| | l | 4字節 | 有符號,機器字節序 | -2147483648 ~ 2147483648| | L | 4字節| 無符號,機器字節序 | 0 ~ 4294967295| | v | 2字節 | 無符號,小端字節序 | 0 ~ 65535| | V | 4字節 | 無符號,小端字節序 | 0 ~ 4294967295| ## 實戰 首先,我們規定如下的協議格式: | 序號| len長度 | 數據| | --- | --- | --- | --- | | 4字節| 4字節| 不定長| 其中,序號為從0開始的自增序號,返回的數據也帶有同樣的序號用于標記同一次請求。長度字段為后續數據的實際長度,因此,一個完整請求的長度為length + 8。 服務器每次接收到的數據中,從第四個字節開始是長度字段,類型為4字節無符號整型。從第八個字節開始是數據體,接收length個字節后結束,記為一個完整數據包。 服務器設置代碼如下所示: ``` $serv->set(array( 'worker_num' => 1, 'open_length_check' => true, // 開啟協議解析 'package_length_type' => 'N', // 長度字段的類型 'package_length_offset' => 4, //第4個字節開始是包長度 'package_body_offset' => 8, //第8個字節開始計算長度 'package_max_length' => 2000000, //協議最大長度 )); ``` 接收數據部分代碼如下: ``` public function onReceive( swoole_server $serv, $fd, $from_id, $data ) { $head = unpack('NN', substr($data, 0 , 8)); // 獲取包頭 $body = substr($data, 8); // 獲取數據 var_dump($body); $response = "Hello"; $num = $head[0]; $len = strlen($response); $content = pack('NN', $num, $len) . $response; // 拼接響應內容 $serv->send($fd, $content); // 發送數據 } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看