搜尋
首頁後端開發php教程php基於websocket搭建簡易聊天室實作_php實例

本文實例講述了php基於websocket搭建簡易聊天室實作。分享給大家供大家參考。具體如下:
1、前言

公司遊戲裡面有個簡單的聊天室,了解了之後才知道是node+websocket做的,想想php也來做個簡單的聊天室。於是蒐集各種資料看文件、找實例自己也寫了個簡單的聊天室。

http連接分為短連接和長連接。短連線一般可以用ajax實現,長連線就是websocket。短連線實作起來比較簡單,但太過於消耗資源。 websocket高效不過相容存在點問題。 websocket是html5的資源

2、前端

前端實作websocket很簡單直接

//连接websocket

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

//成功连接websoc的时候

ws.onopen = function(){}

//成功获取服务端输出的消息

ws.onmessage = function(e){}

//连接错误的时候
ws.onerror = function(){}

//向服务端发送数据

ws.send();

3、後台

websocket的難點主要在後台

3.1websocket連接過程
websocket 通訊圖解 這是一個簡易的客戶端和服務端的通訊圖解,php主要就做的就是接受加密key  並回傳 其中完成套接字的創建和握手操作

下圖是一張詳細的服務端處理websocket的流程圖

3.2 代碼實踐

服務端做的流程大致是:

  1. 掛起一個socket套接字進程等待連線
  2. 有socket連線之後遍歷套接字數組
  3. 沒有握手的進行握手操作,如果已經握手則接收資料解析並寫入緩衝區進行輸出

下面是範例程式碼(我寫的是一個類別所以程式碼是根據函數分段的),文底給出github位址以及自己遇到的一些坑
 1、首先是創建套接字
 

//建立套接字
    public function createSocket($address,$port)
    {
      //创建一个套接字
      $socket= socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
      //设置套接字选项
      socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
      //绑定IP地址和端口
      socket_bind($socket,$address,$port);
      //监听套接字
      socket_listen($socket);
      return $socket;
    }

2、將套接字放入陣列

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

    }

3、掛起進程遍歷套接字數組,主要操作都是在這裡面完成的

public function run(){
      //挂起进程
      while(true){
        $arr=$this->socs;
        $write=$except=NULL;
        //接收套接字数字 监听他们的状态
        socket_select($arr,$write,$except, NULL);
        //遍历套接字数组
        foreach($arr as $k=>$v){
          //如果是新建立的套接字返回一个有效的 套接字资源
          if($this->soc == $v){
            $client=socket_accept($this->soc);
            if($client <0){
              echo "socket_accept() failed";
            }else{
              // array_push($this->socs,$client);
              // unset($this[]);
              //将有效的套接字资源放到套接字数组
              $this->socs[]=$client;
            }
          }else{
            //从已连接的socket接收数据 返回的是从socket中接收的字节数
            $byte=socket_recv($v, $buff,20480, 0);
            //如果接收的字节是0
            if($byte<7)
              continue;
            //判断有没有握手没有握手则进行握手,如果握手了 则进行处理
            if(!$this->hand[(int)$client]){
              //进行握手操作
              $this->hands($client,$buff,$v);
            }else{
              //处理数据操作
              $mess=$this->decodeData($buff);
                //发送数据
              $this->send($mess,$v);
            }
          }
        }
      }
    }

4、進行握手 流程是接收websocket內容從Sec-WebSocket-Key:中獲取key並透過加密演算法寫入緩衝區客戶端會進行驗證(自動驗證不需要我們處理)

public function hands($client,$buff,$v)
    {
      //提取websocket传的key并进行加密 (这是固定的握手机制获取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";
      //将套接字写入缓冲区
      socket_write($v,$new_message,strlen($new_message));
      // socket_write(socket,$upgrade.chr(0), strlen($upgrade.chr(0)));
      //标记此套接字握手成功
      $this->hand[(int)$client]=true;
    }

5、解析客戶端的資料(我這裡沒有進行加密,如果有需要也可以自己加密 )

//解析数据
    public function decodeData($buff)
    {
      //$buff 解析数据帧
      $mask = array(); 
      $data = ''; 
      $msg = unpack('H*',$buff); //用unpack函数从二进制将数据解码
      $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)); 
          //遇到的问题 刚连接的时候就发送数据 显示 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++; 
        }
        //发送数据到客户端
          //如果长度大于125 将数据分块
          $block=str_split($data,125);
          $mess=array(
            'mess'=>$block[0],
            );
        return $mess;          
      }

6、將套接字寫入緩衝區

//发送数据
    public function send($mess,$v)
    {
      //遍历套接字数组 成功握手的 进行数据群发
      foreach ($this->socs as $keys => $values) {
        //用系统分配的套接字资源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、運行方法

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

①最好在控制台運行server.php

到server.php腳本目錄(可以先php -v 看下有沒有設定php如果沒有Linux設定下bash windows 設定下path)

php -f server.php

如果有錯誤會提示

②透過伺服器存取html檔案

8、踩過的坑,打開調試工作方便查看錯誤

①server.php 掛起的進程中可以列印輸出的,如果出現問題可以在程式碼中加入列印來調試

可以在各個判斷裡面做標記在控制台查看程式碼運行在哪個區間

不過每次修改完程式碼後需要重新執行腳本 php server.php

②如果出現這種錯誤可能是

1、在與伺服器初始套接字的時候發送資料 (在第一次與伺服器驗證握手的時候不能發送內容)

2、如果已經驗證過了但是客戶端沒有發送或發送的訊息為空也會出現這樣的情況

所以要檢驗已連接的套接字的資料

 

③可能瀏覽器不支援或服務端沒有開啟socket開始之前最好驗證下

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
解釋負載平衡如何影響會話管理以及如何解決。解釋負載平衡如何影響會話管理以及如何解決。Apr 29, 2025 am 12:42 AM

負載均衡會影響會話管理,但可以通過會話複製、會話粘性和集中式會話存儲解決。 1.會話複製在服務器間複製會話數據。 2.會話粘性將用戶請求定向到同一服務器。 3.集中式會話存儲使用獨立服務器如Redis存儲會話數據,確保數據共享。

說明會話鎖定的概念。說明會話鎖定的概念。Apr 29, 2025 am 12:39 AM

Sessionlockingisatechniqueusedtoensureauser'ssessionremainsexclusivetooneuseratatime.Itiscrucialforpreventingdatacorruptionandsecuritybreachesinmulti-userapplications.Sessionlockingisimplementedusingserver-sidelockingmechanisms,suchasReentrantLockinJ

有其他PHP會議的選擇嗎?有其他PHP會議的選擇嗎?Apr 29, 2025 am 12:36 AM

PHP會話的替代方案包括Cookies、Token-basedAuthentication、Database-basedSessions和Redis/Memcached。 1.Cookies通過在客戶端存儲數據來管理會話,簡單但安全性低。 2.Token-basedAuthentication使用令牌驗證用戶,安全性高但需額外邏輯。 3.Database-basedSessions將數據存儲在數據庫中,擴展性好但可能影響性能。 4.Redis/Memcached使用分佈式緩存提高性能和擴展性,但需額外配

在PHP的上下文中定義'會話劫持”一詞。在PHP的上下文中定義'會話劫持”一詞。Apr 29, 2025 am 12:33 AM

Sessionhijacking是指攻擊者通過獲取用戶的sessionID來冒充用戶。防範方法包括:1)使用HTTPS加密通信;2)驗證sessionID的來源;3)使用安全的sessionID生成算法;4)定期更新sessionID。

PHP的完整形式是什麼?PHP的完整形式是什麼?Apr 28, 2025 pm 04:58 PM

文章討論了PHP,詳細介紹了其完整形式,在We​​b開發中的主要用途,與Python和Java的比較以及對初學者的學習便利性。

PHP如何處理形式數據?PHP如何處理形式數據?Apr 28, 2025 pm 04:57 PM

PHP使用$ \ _ post和$ \ _獲取超級全局的php處理數據,並通過驗證,消毒和安全數據庫交互確保安全性。

PHP和ASP.NET有什麼區別?PHP和ASP.NET有什麼區別?Apr 28, 2025 pm 04:56 PM

本文比較了PHP和ASP.NET,重點是它們對大規模Web應用程序,性能差異和安全功能的適用性。兩者對於大型項目都是可行的,但是PHP是開源和無關的,而ASP.NET,

PHP是對病例敏感的語言嗎?PHP是對病例敏感的語言嗎?Apr 28, 2025 pm 04:55 PM

PHP的情況敏感性各不相同:功能不敏感,而變量和類是敏感的。最佳實踐包括一致的命名和使用對案例不敏感的功能進行比較。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。