91网首页-91网页版-91网在线观看-91网站免费观看-91网站永久视频-91网站在线播放

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

Web sockets — PHP 實(shí)現(xiàn)

admin
2015年7月10日 17:16 本文熱度 7889

自十月底,html5 宣布定稿之后,新一輪的關(guān)于html的討論便開始了,現(xiàn)在這里,我也為大家介紹一種html5標(biāo)準(zhǔn)中提到的新技術(shù) websocket,以及他的 php 實(shí)現(xiàn)范例。

WebSocketHTML5開始提供的一種瀏覽器服務(wù)器間進(jìn)行全雙工通訊的網(wǎng)絡(luò)技術(shù)。WebSocket通信協(xié)議于2011年被IETF定為標(biāo)準(zhǔn)RFC 6455,WebSocketAPIW3C定為標(biāo)準(zhǔn)。

在WebSocket API中,瀏覽器和服務(wù)器只需要做一個(gè)握手的動作,然后,瀏覽器和服務(wù)器之間就形成了一條快速通道。兩者之間就直接可以數(shù)據(jù)互相傳送。

—————-  form wiki

傳統(tǒng)的web程序,都遵循這樣的執(zhí)行方式,瀏覽器發(fā)送一個(gè)請求,然后服務(wù)器端接收這個(gè)請求,處理完成瀏覽器的請求之后,再將處理完成的結(jié)果返回給瀏覽器,然后瀏覽器處理返回的html,將其呈現(xiàn)給用戶。如下圖所示:

server

即使后來出現(xiàn)了ajax這樣的新的技術(shù),它實(shí)際也是使用javascript的api來向服務(wù)器發(fā)送請求,然后等待相應(yīng)的數(shù)據(jù)。也就是說,在瀏覽器和服務(wù)器的交互中,我們每想得到一個(gè)得到新的數(shù)據(jù)(更新頁面,獲得服務(wù)器端的最新狀態(tài))就必須要發(fā)起一個(gè)http請求,建立一條TCP/IP鏈接,當(dāng)這次請求的數(shù)據(jù)被瀏覽器接收到之后,就斷開這條TCP/IP連接。

新的websocket技術(shù),在瀏覽器端發(fā)起一條請求之后,服務(wù)器端與瀏覽器端的請求進(jìn)行握手應(yīng)答之后,就建立起一條長久的,雙工的長連接,基于這條連接,我們不必做一些輪詢就能隨時(shí)獲得服務(wù)器端的狀態(tài),服務(wù)器也不必等待瀏覽器端的請求才能向用戶推送數(shù)據(jù),可以在這條連接上隨時(shí)向以建立websocket連接的用戶 push 數(shù)據(jù)。

這里是 websocket 協(xié)議的 RFC 文檔。

我這里的實(shí)現(xiàn)是基于 php sockets的實(shí)現(xiàn),php socket api.

001<?php
002  class WsServer{
003      public  $socket;
004      public  $socketArray;
005      public  $activatedSocketArray;
006      public function __construct($address,$port){
007        $this->socket =  $this->init($address,$port);
008        if($this->socket == null)
009            exit(1);
010         
011      }
012      private function init($address,$port){
013         $wssocket  = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
014         socket_set_option($wssocket, SOL_SOCKET, SO_REUSEADDR, 1);
015         socket_bind($wssocket,$address,$port);
016         if(socket_listen($wssocket)){
017            $this->p("Socket init success");
018            return $wssocket;
019         }else{
020            $this->p("Socket init failure");
021            exit();
022         }
023          
024      }
025      
026      public function run(){
027        $this->socketArray[] = $this->socket;
028        $write  = NULL;
029        $except = NULL;
030        while (true){
031        $this->activatedSocketArray = $this->socketArray;
032        socket_select($this->activatedSocketArray, $write, $except, null);
033         
034        foreach($this->activatedSocketArray as $s){
035         if($s == $this->socket){
036           $client = socket_accept($this->socket);
037           socket_recv($client, $buffer, 2048, 0);
038          
039           // response a handshake response
040           if(socket_write($client, $this->handshakeResponse($buffer))!== false){
041             $this->p('add a socket into the queue');
042             array_push($this->socketArray, $client);
043            }else{
044               $this->p('error on handshake');
045               $this->errorLog(socket_last_error());
046           }
047        }else{
048            socket_recv($s, $buffer, 2048, 0);
049             
050            $frame = $this->parseFrame($buffer);
051            var_dump($frame);
052            $str  = $this->decode($buffer);
053            $str = $this->frame($str);
054            socket_write($s,$str,strlen($str));
055          }
056        }
057         
058        }
059      }
060      /**
061       *  parse the frame
062       * */
063      private function parseFrame($d){
064        $firstByte = ord(substr($d,0,1));
065        $result =array();
066        $result['FIN'] = $this->getBit($firstByte,1);
067        $result['opcode'] = $firstByte & 15;
068        $result['length'] = ord(substr($d,1,1)) & 127;
069        return $result;
070      }
071      private function getBit($m,$n){
072         return  ($n >> ($m-1)) & 1; 
073      }
074      /*
075       *   build the data frame sent to client by server socket. 
076       *
077       * **/
078      function frame($s){
079        $a = str_split($s, 125);
080        if (count($a) == 1){
081            return "\x81" . chr(strlen($a[0])) . $a[0];
082        }
083        $ns = "";
084        foreach ($a as $o){
085            $ns .= "\x81" . chr(strlen($o)) . $o;
086        }
087        return $ns;
088      }
089      /*
090       * decode the client socket input
091       *
092       * **/
093      function decode($buffer) {
094        $len = $masks = $data = $decoded = null;
095        $len = ord($buffer[1]) & 127;
096       
097        if ($len === 126) {
098            $masks = substr($buffer, 4, 4);
099            $data = substr($buffer, 8);
100        }
101        else if ($len === 127) {
102            $masks = substr($buffer, 10, 4);
103            $data = substr($buffer, 14);
104        }
105        else {
106            $masks = substr($buffer, 2, 4);
107            $data = substr($buffer, 6);
108        }
109         
110        for ($index = 0; $index < strlen($data); $index++) {
111            $decoded .= $data[$index] ^ $masks[$index % 4];
112        }
113        return $decoded;
114      }
115    /*
116     * params @requestHeaders : read from request socket
117     * return an array of request
118     *
119     * */
120    function parseHeaders($requsetHeaders){
121        $resule =array();
122        if (preg_match("/GET (.*) HTTP/"              ,$requsetHeaders,$match)) { $resule['reuqest'] = $match[1]; }
123        if (preg_match("/Host: (.*)\r\n/"             ,$requsetHeaders,$match)) { $result['host'] = $match[1]; }
124        if (preg_match("/Origin: (.*)\r\n/"           ,$requsetHeaders,$match)) { $result['origin'] = $match[1]; }
125        if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$requsetHeaders,$match)) { $result['key'] = $match[1]; }
126        return $result;
127         
128    }
129    /*
130     * protocol version : 13
131     * generting the key of handshaking
132     * return encrypted key
133     * */
134    function getKey($requestKey){
135        return base64_encode(sha1($requestKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
136         
137    }
138    /**params @parseRequest : request written in socket
139     * return handshakResponse witten in response socket
140     * */
141    function  handshakeResponse($request){
142        $parsedRequest  = $this->parseHeaders($request);
143        $encryptedKey = $this->getKey($parsedRequest['key']);
144        $response  = "HTTP/1.1 101 Switching Protocol\r\n" .
145                    "Upgrade: websocket\r\n" .
146                    "Connection: Upgrade\r\n" .
147                    "Sec-WebSocket-Accept: " .$encryptedKey. "\r\n\r\n";
148        return $response;
149                     
150    }
151    /*
152     * report last_error in socket
153     *
154     * */
155    function errorLog($ms){
156        echo 'Error:\n'.$ms;
157    }
158    /*
159     * print the log
160     *
161     * */
162    private  function p($e){
163        echo $e."\n";
164    }
165   function test(){
166      $read[] = $this->socket;
167      $write = null;
168      $except = null;
169      socket_select($read, $write, $except,null);
170      var_dump($read);
171   }
172  }
173  $w = new WsServer('localhost',4000);
174  $w->run();
175?>

 

這篇文章中對這里的代碼的有些地方做了些相關(guān)的解釋

這個(gè)類主要實(shí)現(xiàn)了對websocket的握手回應(yīng),將每一個(gè)連接成功的websocket加入到一個(gè)數(shù)組中之后,就能夠在服務(wù)器端對多個(gè)websocket 客戶端進(jìn)行處理。

對websocket的握手請求,在接收到的報(bào)文中 會得到一個(gè) Sec-WebSocket-Key 字段,要把“Sec-WebSocket-Key”加上一個(gè)魔幻字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”。使用SHA-1加密,之后進(jìn)行BASE-64編碼,將結(jié)果做為“Sec-WebSocket-Accept”頭的值,返回給客戶端。這樣就完成了與客戶端之間的握手。

之后,就能在服務(wù)器端監(jiān)聽客戶端發(fā)來的請求了,同時(shí)也可以操作在服務(wù)端的socket句柄,來向?yàn)g覽器推送消息。


該文章在 2015/7/10 17:16:19 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 日韩欧美国产精品区 | 青青不卡| 99热精品在线 | 国产高清一 | 激情文学小说区另 | 日韩成人AⅤ| 国产精品一二在线 | 国产精品在里面 | 午夜国产精品理论 | 日本乱理伦片 | 91福利一区二区 | 国产精品视频顷一区 | 国产视频第二页 | 精品一区二区视频 | 韩国三级 | 最新国产手机在线观看 | 日本在线一区二 | 日韩在线视频一 | 国产伊人 | 区三区免费中文字幕 | 国产大片免费观看 | 国产欧美在线视频免 | 日韩欧美亚洲国产 | 97国产在线视频 | 日韩欧美国产aⅴ | 日本中文字幕熟女 | 欧美日韩在线亚洲 | 欧洲乱码| 91视频在线网站 | 欧洲亚洲精| 中文字幕精品一区 | 国产不卡在线二区 | 欧美一区亚洲二区 | 国产亚洲精品福利片 | 国产外部专区一朋友 | 日本黄在线 | 精品国产动漫日 | 99热在线只有精品 | 日本在线播放 | 果冻影视 | 国产精品秘A级导航 |