首頁 後端開發 php教程 php實作socket推送技術

php實作socket推送技術

Jul 07, 2018 pm 01:44 PM
php實現

這篇文章主要介紹了關於php實現socket推送技術,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

在socket出現之前已經有ajax定時請求、長輪詢等方案,但都不能滿足需求,socket就應用而生了。

socket基本函數socket

總結下常用的socket函數

服務端: socket_create 建立socket設定基本參數 

#     socket_bind

   

     socket_listen 監聽

     socket_accept 用戶端的連線

     socket_read 的連線

     socket_read 的連線

##  

#     socket_close關閉連線

客戶端:socket_create 建立socket設定基本參數 

     socket_connect 連線socket

     服務socket 連線socket

     服務socket_Fwrite 傳送給服務端」發送資料給服務端」給服務者

     socket_close 關閉連線

H5websocket不多說了,上連結

OK,開始貼程式碼~

--------- -------------------------------------------------分割線

服務端程式碼:

<?php
class WS {
    var $master;
    var $sockets = array();
    var $debug = false;//true为调试模式,输出log日志
    var $handshake = array();

    function __construct($address, $port){
        $this->master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP)     or die("socket_create() failed");
        socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1)  or die("socket_option() failed");
        socket_bind($this->master, $address, $port)                    or die("socket_bind() failed");
        socket_listen($this->master,20)                                or die("socket_listen() failed");
        
        $this->sockets[] = $this->master;
        $this->say("Server Started : ".date(&#39;Y-m-d H:i:s&#39;));
        $this->say("Listening on   : ".$address." port ".$port);
        $this->say("Master socket  : ".$this->master."\n");
        
        while(true){
            $socketArr = $this->sockets;
            $write = NULL;
            $except = NULL;
            socket_select($socketArr, $write, $except, NULL);  //自动选择来消息的socket 如果是握手 自动选择主机
            foreach ($socketArr as $socket){
                if ($socket == $this->master){  //主机
                    $client = socket_accept($this->master);
                    if ($client < 0){
                        $this->log("socket_accept() failed");
                        continue;
                    } else{
                        $this->connect($client);
                    }
                } else {
                    $bytes = @socket_recv($socket,$buffer,2048,0);
                    if ($bytes == 0){
                        $this->disConnect($socket);
                    }
                    else{
                        $key = array_search($socket, $this->sockets);
                        if (empty($this->handshake) || !isset($this->handshake[$key]) || !$this->handshake[$key]){
                            $this->doHandShake($socket, $buffer, $key);
                        }
                        else{
                            $buffer = $this->decode($buffer);
                            echo $buffer.PHP_EOL;
                            $key = array_search($socket, $this->sockets);
                            $arr = $this->sockets;
                            array_shift($arr);
                            foreach ($arr as $s){
                                $this->send($s, $buffer);
                            }
                        }
                    }
                }
            }
        }
    }
    
    function send($client, $msg){
        $msg = $this->frame($msg);
        socket_write($client, $msg, strlen($msg));
    }
    function connect($socket){
        array_push($this->sockets, $socket);
        $this->say("\n" . $socket . " CONNECTED!");
        $this->say(date("Y-n-d H:i:s"));
    }
    function disConnect($socket){
        $index = array_search($socket, $this->sockets);
        socket_close($socket);
        $this->say($socket . " DISCONNECTED!");
        if ($index >= 0){
            echo &#39;unset index is:&#39;.PHP_EOL;
            unset($this->sockets[$index]);
        }
    }
    function doHandShake($socket, $buffer, $handKey){
        $this->log("\nRequesting handshake...");
        $this->log($buffer);
        list($resource, $host, $origin, $key) = $this->getHeaders($buffer);
        $this->log("Handshaking...");
        $upgrade  = "HTTP/1.1 101 Switching Protocol\r\n" .
                    "Upgrade: websocket\r\n" .
                    "Connection: Upgrade\r\n" .
                    "Sec-WebSocket-Accept: " . $this->calcKey($key) . "\r\n\r\n";  //必须以两个回车结尾
        $this->log($upgrade);
        $sent = socket_write($socket, $upgrade, strlen($upgrade));
        $this->handshake[$handKey]=true;
        $this->log("Done handshaking...");
        return true;
    }

    function getHeaders($req){
        $r = $h = $o = $key = null;
        if (preg_match("/GET (.*) HTTP/"              ,$req,$match)) { $r = $match[1]; }
        if (preg_match("/Host: (.*)\r\n/"             ,$req,$match)) { $h = $match[1]; }
        if (preg_match("/Origin: (.*)\r\n/"           ,$req,$match)) { $o = $match[1]; }
        if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$req,$match)) { $key = $match[1]; }
        return array($r, $h, $o, $key);
    }

    function calcKey($key){
        //基于websocket version 13
        $accept = base64_encode(sha1($key . &#39;258EAFA5-E914-47DA-95CA-C5AB0DC85B11&#39;, true));
        return $accept;
    }

    function decode($buffer) {
        $len = $masks = $data = $decoded = null;
        $len = ord($buffer[1]) & 127;

        if ($len === 126) {
            $masks = substr($buffer, 4, 4);
            $data = substr($buffer, 8);
        } 
        else if ($len === 127) {
            $masks = substr($buffer, 10, 4);
            $data = substr($buffer, 14);
        } 
        else {
            $masks = substr($buffer, 2, 4);
            $data = substr($buffer, 6);
        }
        for ($index = 0; $index < strlen($data); $index++) {
            $decoded .= $data[$index] ^ $masks[$index % 4];
        }
        return $decoded;
    }

    function frame($s){
        $a = str_split($s, 125);
        if (count($a) == 1){
            return "\x81" . chr(strlen($a[0])) . $a[0];
        }
        $ns = "";
        foreach ($a as $o){
            $ns .= "\x81" . chr(strlen($o)) . $o;
        }
        return $ns;
    }

    
    function say($msg = ""){
        echo $msg . "\n";
    }
    function log($msg = ""){
        if ($this->debug){
            echo $msg . "\n";
        } 
    }
}
    

new WS(&#39;localhost&#39;, 4000);
登入後複製

客戶端程式碼(H5):

<html>
    <head>
        <title>demo</title>
        <script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script>
    </head>
    <body>
    <input type="text" id="content">
    <input type="button" value="send" id="send">
        <script type="text/javascript">                    var ws = new WebSocket("ws://localhost:4000");
            ws.onopen = function(){
                console.log("握手成功");
            }
            ws.onmessage = function(e){
                console.log("message:" + e.data);
            }
            ws.onerror = function(){
                console.log("error");
            }
            $("#send").click(function(){
                content = $("#content").val();
                console.log(content);
                ws.send(content);
            })        </script>
    </body>
</html>
登入後複製

然後執行php demo.php 開啟socket(從運維那偷學一招,linux下執行nohup php demo.php &可以在後台執行) ,瀏覽器開啟多個index.html,就能建立通訊了。

程式碼解析:

1.屬性$sockets陣列保存每個accept連接(不知道這麼描述對不對); 

2.屬性$handshake陣列保存連線是否在連線狀態;

以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網!

相關推薦:
PHP中使用Elasticsearch的方法

 

PHP的批次更新######

以上是php實作socket推送技術的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱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

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

控制快取失效時間如何在PHP中實現? 控制快取失效時間如何在PHP中實現? Jun 19, 2023 pm 11:23 PM

隨著網路應用的普及,網站響應速度越來越成為用戶關注的重點。為了快速回應用戶的請求,網站往往採用快取技術快取數據,從而減少資料庫查詢次數。但是,快取的過期時間對反應速度有著重要影響。本文將對控制快取失效時間的方法進行探討,以幫助PHP開發者更好地應用快取技術。一、什麼是快取失效時間?快取失效時間是指快取中的資料被認為已經過期的時間。它決定了快取中的資料何時需

如何使用 PHP 實作檔案轉換和格式轉換功能 如何使用 PHP 實作檔案轉換和格式轉換功能 Sep 05, 2023 pm 03:40 PM

如何使用PHP實作檔案轉換和格式轉換功能1.引言在開發Web應用程式過程中,我們經常需要實作檔案轉換和格式轉換的功能。無論是將圖片檔案轉換為其他格式,還是將文字檔案從一種編碼轉換為另一種編碼,這些操作都是常見的需求。本文將介紹如何使用PHP實作這些功能,並附帶程式碼範例。 2.檔案轉換2.1將圖片檔案轉換為其他格式在PHP中,我們可以使用

PHP實現的線上投票系統的使用者隱私保護 PHP實現的線上投票系統的使用者隱私保護 Aug 09, 2023 am 10:29 AM

PHP實現的線上投票系統的使用者隱私保護隨著網路的發展和普及,越來越多的投票活動開始轉移到線上平台進行。線上投票系統的便利性為用戶帶來了許多好處,但同時也引發了用戶隱私外洩的擔憂。隱私保護已經成為線上投票系統設計的重要方面。本文將介紹如何使用PHP編寫一個線上投票系統,並重點介紹用戶隱私保護的問題。在設計和開發線上投票系統時,需要遵循以下幾個原則來保

如何使用 PHP 實現行動端適配與響應式設計 如何使用 PHP 實現行動端適配與響應式設計 Sep 05, 2023 pm 01:04 PM

如何使用PHP實現行動端適配和響應式設計行動端適配和響應式設計是現代網站開發中重要的實踐,它們能夠保證網站在不同裝置上的良好展示效果。在本文中,我們將介紹如何使用PHP實現行動端適配和響應式設計,並附帶程式碼範例。一、理解行動端適配和響應式設計的概念行動端適配是指根據設備的不同特性和尺寸,針對不同的設備提供不同的樣式和佈局。而響應式設計則是指透過使用

如何利用PHP實現用戶註冊功能 如何利用PHP實現用戶註冊功能 Sep 25, 2023 pm 06:13 PM

如何利用PHP實現用戶註冊功能在現代的網路應用程式中,用戶註冊功能是一個非常常見的需求。透過註冊功能,使用者可以建立自己的帳戶並使用相應的功能。本文將透過PHP程式語言來實現使用者註冊功能,並提供詳細的程式碼範例。首先,我們需要建立一個HTML表單,用於接收使用者的註冊資訊。在表單中,我們需要包含一些輸入字段,如使用者名稱、密碼、郵箱等。可根據實際需求自訂表單欄位。

PHP資料快取的一致性雜湊演算法實作原理 PHP資料快取的一致性雜湊演算法實作原理 Aug 10, 2023 am 11:10 AM

PHP資料快取的一致性雜湊演算法實作原理一致性雜湊演算法(ConsistentHashing)是一種常用於分散式系統中資料快取的演算法,可以在系統擴展和縮減時,最小化資料遷移的數量。在PHP中,實作一致性雜湊演算法可以提高資料快取的效率和可靠性,本文將介紹一致性雜湊演算法的原理,並提供程式碼範例。一致性哈希演算法的基本原理傳統的哈希演算法將資料分散到不同的節點上,但當節點

PHP如何實現微信小程式指紋登陸 PHP如何實現微信小程式指紋登陸 May 31, 2023 pm 10:40 PM

隨著微信小程式的不斷發展,越來越多的使用者開始選擇微信小程式進行登陸。為了提高使用者的登入體驗,微信小程式開始支援指紋登陸。在本文中,我們將會介紹如何使用PHP來實現微信小程式的指紋登陸。一、了解微信小程式的指紋登陸在微信小程式的基礎上,開發者可以使用微信的指紋辨識功能,讓使用者透過指紋登陸微信小程序,從而提高登入體驗的安全性和便利性。二、準備工作在使用PHP實現

如何使用 PHP 實現數據分析和報表生成 如何使用 PHP 實現數據分析和報表生成 Sep 06, 2023 pm 03:07 PM

如何使用PHP實現資料分析和報表產生簡介:在現今的資訊時代,資料分析和報表產生是企業決策不可或缺的一部分。幸運的是,使用PHP程式語言可以輕鬆實現這項功能。本篇文章將介紹如何使用PHP實現資料分析和報表產生的基本方法和技巧,同時提供一些程式碼範例。一、資料分析資料收集首先,我們需要收集和準備要分析的資料。資料可以來自於各種來源,如資料庫、日誌檔案、

See all articles