最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

php基于websocket搭建簡(jiǎn)易聊天室實(shí)踐

 更新時(shí)間:2016年10月24日 14:46:49   作者:StudyBlog  
本篇文章主要講解php+websocket搭建簡(jiǎn)易聊天室實(shí)踐,文中有關(guān)php,websocket的內(nèi)容,請(qǐng)有需要的人參考。

本文實(shí)例講述了php基于websocket搭建簡(jiǎn)易聊天室實(shí)踐。分享給大家供大家參考。具體如下:
1、前言

公司游戲里面有個(gè)簡(jiǎn)單的聊天室,了解了之后才知道是node+websocket做的,想想php也來做個(gè)簡(jiǎn)單的聊天室。于是搜集各種資料看文檔、找實(shí)例自己也寫了個(gè)簡(jiǎn)單的聊天室。

http連接分為短連接和長(zhǎng)連接。短連接一般可以用ajax實(shí)現(xiàn),長(zhǎng)連接就是websocket。短連接實(shí)現(xiàn)起來比較簡(jiǎn)單,但是太過于消耗資源。websocket高效不過兼容存在點(diǎn)問題。websocket是html5的資源

2、前端

前端實(shí)現(xiàn)websocket很簡(jiǎn)單直接

//連接websocket

var ws = new WebSocket("ws://127.0.0.1:8000");

//成功連接websoc的時(shí)候

ws.onopen = function(){}

//成功獲取服務(wù)端輸出的消息

ws.onmessage = function(e){}

//連接錯(cuò)誤的時(shí)候
ws.onerror = function(){}

//向服務(wù)端發(fā)送數(shù)據(jù)

ws.send();

3、后臺(tái)

websocket的難點(diǎn)主要在后臺(tái)

3.1websocket連接過程
websocket 通信圖解 這是一個(gè)簡(jiǎn)易的客戶端和服務(wù)端的通信圖解,php主要就做的就是接受加密key  并返回 其中完成套接字的創(chuàng)建和握手操作

下圖是一張?jiān)敿?xì)的服務(wù)端處理websocket的流程圖

3.2 代碼實(shí)踐

服務(wù)端做的流程大致是:

  1. 掛起一個(gè)socket套接字進(jìn)程等待連接
  2. 有socket連接之后遍歷套接字?jǐn)?shù)組
  3. 沒有握手的進(jìn)行握手操作,如果已經(jīng)握手則接收數(shù)據(jù)解析并寫入緩沖區(qū)進(jìn)行輸出

下面是示例代碼(我寫的是一個(gè)類所以代碼是根據(jù)函數(shù)分段的),文底給出github地址以及自己遇到的一些坑
 1、首先是創(chuàng)建套接字
 

//建立套接字
    public function createSocket($address,$port)
    {
      //創(chuàng)建一個(gè)套接字
      $socket= socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
      //設(shè)置套接字選項(xiàng)
      socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
      //綁定IP地址和端口
      socket_bind($socket,$address,$port);
      //監(jiān)聽套接字
      socket_listen($socket);
      return $socket;
    }

2、將套接字放入數(shù)組

public function __construct($address,$port)
    {
      //建立套接字
      $this->soc=$this->createSocket($address,$port);
      $this->socs=array($this->soc);

    }

3、掛起進(jìn)程遍歷套接字?jǐn)?shù)組,主要操作都是在這里面完成的

public function run(){
      //掛起進(jìn)程
      while(true){
        $arr=$this->socs;
        $write=$except=NULL;
        //接收套接字?jǐn)?shù)字 監(jiān)聽他們的狀態(tài)
        socket_select($arr,$write,$except, NULL);
        //遍歷套接字?jǐn)?shù)組
        foreach($arr as $k=>$v){
          //如果是新建立的套接字返回一個(gè)有效的 套接字資源
          if($this->soc == $v){
            $client=socket_accept($this->soc);
            if($client <0){
              echo "socket_accept() failed";
            }else{
              // array_push($this->socs,$client);
              // unset($this[]);
              //將有效的套接字資源放到套接字?jǐn)?shù)組
              $this->socs[]=$client;
            }
          }else{
            //從已連接的socket接收數(shù)據(jù) 返回的是從socket中接收的字節(jié)數(shù)
            $byte=socket_recv($v, $buff,20480, 0);
            //如果接收的字節(jié)是0
            if($byte<7)
              continue;
            //判斷有沒有握手沒有握手則進(jìn)行握手,如果握手了 則進(jìn)行處理
            if(!$this->hand[(int)$client]){
              //進(jìn)行握手操作
              $this->hands($client,$buff,$v);
            }else{
              //處理數(shù)據(jù)操作
              $mess=$this->decodeData($buff);
                //發(fā)送數(shù)據(jù)
              $this->send($mess,$v);
            }
          }
        }
      }
    }

4、進(jìn)行握手 流程是接收websocket內(nèi)容從Sec-WebSocket-Key:中獲取key并通過加密算法寫入緩沖區(qū)客戶端會(huì)進(jìn)行驗(yàn)證(自動(dòng)驗(yàn)證不需要我們處理)

public function hands($client,$buff,$v)
    {
      //提取websocket傳的key并進(jìn)行加密 (這是固定的握手機(jī)制獲取Sec-WebSocket-Key:里面的key)
      $buf = substr($buff,strpos($buff,'Sec-WebSocket-Key:')+18);
      //去除換行空格字符
      $key = trim(substr($buf,0,strpos($buf,"\r\n")));
       //固定的加密算法
      $new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));
      $new_message = "HTTP/1.1 101 Switching Protocols\r\n";
      $new_message .= "Upgrade: websocket\r\n";
      $new_message .= "Sec-WebSocket-Version: 13\r\n";
      $new_message .= "Connection: Upgrade\r\n";
      $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";
      //將套接字寫入緩沖區(qū)
      socket_write($v,$new_message,strlen($new_message));
      // socket_write(socket,$upgrade.chr(0), strlen($upgrade.chr(0)));
      //標(biāo)記此套接字握手成功
      $this->hand[(int)$client]=true;
    }

5、解析客戶端的數(shù)據(jù)(我這里沒有進(jìn)行加密,如果有需要也可以自己加密 )

//解析數(shù)據(jù)
    public function decodeData($buff)
    {
      //$buff 解析數(shù)據(jù)幀
      $mask = array(); 
      $data = ''; 
      $msg = unpack('H*',$buff); //用unpack函數(shù)從二進(jìn)制將數(shù)據(jù)解碼
      $head = substr($msg[1],0,2); 
      if (hexdec($head{1}) === 8) { 
        $data = false; 
      }else if (hexdec($head{1}) === 1){ 
        $mask[] = hexdec(substr($msg[1],4,2)); 
        $mask[] = hexdec(substr($msg[1],6,2)); 
        $mask[] = hexdec(substr($msg[1],8,2)); 
        $mask[] = hexdec(substr($msg[1],10,2)); 
          //遇到的問題 剛連接的時(shí)候就發(fā)送數(shù)據(jù) 顯示 state connecting
        $s = 12; 
        $e = strlen($msg[1])-2; 
        $n = 0; 
        for ($i=$s; $i<= $e; $i+= 2) { 
          $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2))); 
          $n++; 
        }
        //發(fā)送數(shù)據(jù)到客戶端
          //如果長(zhǎng)度大于125 將數(shù)據(jù)分塊
          $block=str_split($data,125);
          $mess=array(
            'mess'=>$block[0],
            );
        return $mess;          
      }

6、將套接字寫入緩沖區(qū)

//發(fā)送數(shù)據(jù)
    public function send($mess,$v)
    {
      //遍歷套接字?jǐn)?shù)組 成功握手的 進(jìn)行數(shù)據(jù)群發(fā)
      foreach ($this->socs as $keys => $values) {
        //用系統(tǒng)分配的套接字資源id作為用戶昵稱
          $mess['name']="Tourist's socket:{$v}";
          $str=json_encode($mess);
          $writes ="\x81".chr(strlen($str)).$str;
          // ob_flush();
          // flush();
          // sleep(3);
          if($this->hand[(int)$values])
            socket_write($values,$writes,strlen($writes));
        }
    }

7、運(yùn)行方法

github地址git@github.com:rsaLive/websocket.git

①最好在控制臺(tái)運(yùn)行server.php

轉(zhuǎn)到server.php腳本目錄(可以先php -v 看下有沒有配置php如果沒有Linux配置下bash windows 配置下path)

php -f server.php

如果有錯(cuò)誤會(huì)提示

②通過服務(wù)器訪問html文件

8、踩過的坑,打開調(diào)試工作方便查看錯(cuò)誤

①server.php 掛起的進(jìn)程中可以打印輸出的,如果出現(xiàn)問題可以在代碼中加入打印來調(diào)試

可以在各個(gè)判斷里面做標(biāo)記在控制臺(tái)查看代碼運(yùn)行在哪個(gè)區(qū)間

不過每次修改完代碼之后需要重新運(yùn)行腳本 php server.php

②如果出現(xiàn)這種錯(cuò)誤可能是

1、在與服務(wù)器初始套接字的時(shí)候發(fā)送數(shù)據(jù) (在第一次與服務(wù)器驗(yàn)證握手的時(shí)候不能發(fā)送內(nèi)容)

2、如果已經(jīng)驗(yàn)證過了但是客戶端沒有發(fā)送或者發(fā)送的消息為空也會(huì)出現(xiàn)這樣的情況

所以要檢驗(yàn)已連接的套接字的數(shù)據(jù)

 

③可能瀏覽器不支持或者服務(wù)端沒有開啟socket開始之前最好驗(yàn)證下

if (window.WebSocket){
  console.log("This browser supports WebSocket!");
} else {
  console.log("This browser does not support WebSocket.");
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • php獲取qq用戶昵稱和在線狀態(tài)(實(shí)例分析)

    php獲取qq用戶昵稱和在線狀態(tài)(實(shí)例分析)

    獲取qq在線狀態(tài)官方已有API提供了,我們用另一種方法獲取qq用戶昵稱和在線狀態(tài),主要是為學(xué)習(xí)PHP。
    2013-10-10
  • PHP單例模式詳解及實(shí)例代碼

    PHP單例模式詳解及實(shí)例代碼

    本文介紹PHP單例模式,文中講解了單例模式的概念、單例模式的特點(diǎn)、使用單例模式的原因及場(chǎng)景及PHP單例模式代碼實(shí)例,需要的碼農(nóng)可以參考下
    2016-12-12
  • Laravel框架源碼解析之模型Model原理與用法解析

    Laravel框架源碼解析之模型Model原理與用法解析

    這篇文章主要介紹了Laravel框架源碼解析之模型Model,結(jié)合實(shí)例形式分析了Laravel框架模型Model相關(guān)原理、用法及操作注意事項(xiàng),需要的朋友可以參考下
    2020-05-05
  • Yii2中的場(chǎng)景(scenario)和驗(yàn)證規(guī)則(rule)詳解

    Yii2中的場(chǎng)景(scenario)和驗(yàn)證規(guī)則(rule)詳解

    Yii2的rule用于對(duì)模型屬性進(jìn)行驗(yàn)證,scenario用戶定義不同場(chǎng)景下需要驗(yàn)證的模型,下面這篇文章主要給大家介紹了關(guān)于Yii2中場(chǎng)景(scenario)和驗(yàn)證規(guī)則(rule)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。
    2018-01-01
  • Yii2創(chuàng)建表單(ActiveForm)方法詳解

    Yii2創(chuàng)建表單(ActiveForm)方法詳解

    這篇文章主要介紹了Yii2創(chuàng)建表單(ActiveForm)的方法,結(jié)合實(shí)例形式詳細(xì)分析了Yii創(chuàng)建表單的詳細(xì)步驟及相關(guān)函數(shù)與屬性的使用技巧,需要的朋友可以參考下
    2016-07-07
  • php socket通信簡(jiǎn)單實(shí)現(xiàn)

    php socket通信簡(jiǎn)單實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了php簡(jiǎn)單實(shí)現(xiàn)socket通信的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 分享5個(gè)非常有用的Laravel Blade指令

    分享5個(gè)非常有用的Laravel Blade指令

    這篇文章主要給大家分享介紹了5個(gè)非常有用的Laravel Blade指令,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • 回帖的圖片實(shí)現(xiàn)代碼

    回帖的圖片實(shí)現(xiàn)代碼

    其實(shí)原理就是通過php的session判斷,發(fā)帖前后不同的session值進(jìn)行判斷,需要的朋友可以自由發(fā)揮下
    2014-02-02
  • PHP中上傳文件打印錯(cuò)誤錯(cuò)誤類型分析

    PHP中上傳文件打印錯(cuò)誤錯(cuò)誤類型分析

    這篇文章主要介紹了PHP中上傳文件打印錯(cuò)誤,錯(cuò)誤類型分析 ,需要的朋友可以參考下
    2019-04-04
  • php微信小程序解包過程實(shí)例詳解

    php微信小程序解包過程實(shí)例詳解

    這篇文章主要介紹了php微信小程序解包過程實(shí)例詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03

最新評(píng)論

白山市| 无极县| 潼南县| 太保市| 延吉市| 永川市| 平乡县| 夏河县| 阜新| 铜山县| 枣强县| 滦南县| 临沧市| 哈巴河县| 颍上县| 开化县| 平罗县| 新平| 报价| 星座| 陆川县| 田阳县| 武冈市| 绥芬河市| 且末县| 梓潼县| 平原县| 新巴尔虎右旗| 安泽县| 西峡县| 呼伦贝尔市| 大名县| 乐安县| 蓝山县| 屏南县| 永靖县| 宜阳县| 深泽县| 化德县| 泰宁县| 德安县|