日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > php >内容正文

php

php怎么实现即时聊天,php实现socket即时通讯示例

發(fā)布時(shí)間:2025/3/20 php 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php怎么实现即时聊天,php实现socket即时通讯示例 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在socket出現(xiàn)之前已經(jīng)有ajax定時(shí)請(qǐng)求、長(zhǎng)輪詢等方案,但都不能滿足某些特定情況下的需求,基于此,socket就應(yīng)運(yùn)而生了。

總結(jié)下常用的socket函數(shù)

服務(wù)端: socket_create 創(chuàng)建socket設(shè)置基本參數(shù)

socket_bind 綁定ip和端口號(hào)

socket_listen 監(jiān)聽

socket_accept 客戶端的連接

socket_read 讀取客戶端的數(shù)據(jù)

socket_write 給單獨(dú)客戶端發(fā)送數(shù)據(jù)

socket_close 關(guān)閉連接

客戶端:socket_create 創(chuàng)建socket設(shè)置基本參數(shù)

socket_connect 連接socket

socket_write 給服務(wù)端發(fā)送數(shù)據(jù)

socket_read 讀取服務(wù)端數(shù)據(jù)

socket_close 關(guān)閉連接

服務(wù)端代碼socket.php(名字自己定義):

class WS {

var $master;

var $sockets = array();

var $debug = false;//true為調(diào)試模式,輸出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('Y-m-d H:i:s'));

$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); //自動(dòng)選擇來消息的socket 如果是握手 自動(dòng)選擇主機(jī)

foreach ($socketArr as $socket){

if ($socket == $this->master){ //主機(jī)

$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);

$msg = $this->frame('恭喜你,成功了');

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 'unset index is:'.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"; //必須以兩個(gè)回車結(jié)尾

$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 . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', 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('localhost', 4000);

客戶端代碼index.html(H5):

demo

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);

})

然后到socket.php所在的目錄執(zhí)行php socket.php 開啟socket(直接使用php命令要添加環(huán)境變量),linux下執(zhí)行nohup php demo.php &可以在后臺(tái)執(zhí)行,瀏覽器打開多個(gè)index.html,就能建立通訊了。

總結(jié)

以上是生活随笔為你收集整理的php怎么实现即时聊天,php实现socket即时通讯示例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。