php使用Socket实现聊天室功能(书中的代码)
这只是一种技术
<?php
$host = "127.0.0.1";
// 指定监听的端口,注意该端口不能与现有应用的端口冲突
$port = '9505';
$null = null;
// 创建Socket。AF_INET:代表通信时使用IPv4协议;SOCK_STREAM:代表传输的数据是二进制流数据;SOL_TCP:代表底层使用的协议是TCP
$socket = socket_create ( AF_INET, SOCK_STREAM, SOL_TCP );
// 指定Socket相应的属性。SOL_SOCKET:设定协议的等级;SO_REUSEADDR:设置端口释放之后可以立即被使用
socket_set_option ( $socket, SOL_SOCKET, SO_REUSEADDR, 1 );
// 绑定端口
socket_bind ( $socket, 0, $port );
// 监听端口
socket_listen ( $socket );
// 声明一个数组,用于存放所有的客户端连接
$clients = array (
$socket
);
while ( true ) {
$changed_socket = $clients;
// 在当前数组中获取活跃的Socket连接,即当前正在发送请求的连接或正在传输数据的连接等
socket_select ( $changed_socket, $null, $null, 0, 10 );
// 判断当前的Socket是否为活跃的Socket,如果是,说明客户端在请求连接
if (in_array ( $socket, $changed_socket )) {
echo "client connecting";
// 接受连接
$socket_new = socket_accept ( $socket );
$clients [] = $socket_new;
// 发送握手信息
$header = socket_read ( $socket_new, 1024 );
perform_handshaking ( $header, $socket_new, $host, $port );
// 在连接成功后,当前Socket要从活跃Socket列表中删除,否则会陷入死循环
$key = array_search ( $socket, $changed_socket );
unset ( $changed_socket [$key] );
} else {
// 不是新连接,是客户端在发送数据
// 服务器开始读取客户端发送的数据
foreach ( $changed_socket as $v ) {
while ( socket_recv ( $v, $buf, 1024, 0 ) >= 1 ) {
// 解包数据
$received_text = unmask ( $buf );
// 将数据解包后转成JSON对象
$msgJson = json_decode ( $received_text );
// 读取数据
$namer = $msgJson->namer;
$content = $msgJson->content;
// 将数据进行编码
$message = mask ( json_encode ( [
'namer' => $namer,
'content' => $content,
'type' => 'usermsg'
] ) );
// 广播编码后的数据。服务器进行广播的消息会触发客户端的onmessage事件
send_message ( $message );
// 跳出foreach循环
break 2;
}
// 删除已经关闭的Socket
$buf = @socket_read ( $v, 1024, PHP_NORMAL_READ );
if ($buf === false) {
$key = array_search ( $v, $clients );
socket_getpeername ( $v, $ip );
unset ( $clients [$key] );
$msg = mask ( json_encode ( [
'type' => 'system',
'content' => $ip . "已经下线。"
] ) );
send_message ( $msg );
}
}
}
}
// 发送消息的方法
function send_message($msg) {
global $clients;
foreach ( $clients as $changed_socket ) {
@socket_write ( $changed_socket, $msg, strlen ( $msg ) );
}
return true;
}
// 以下3个函数,我们只需了解总体结构即可。在有需要时可以直接使用
// 解码数据。服务器解码客户端发送过来的数据
function unmask($text) {
$length = ord ( $text [1] ) & 127;
if ($length == 126) {
$masks = substr ( $text, 4, 4 );
$data = substr ( $text, 8 );
} elseif ($length == 127) {
$masks = substr ( $text, 10, 4 );
$data = substr ( $text, 14 );
} else {
$masks = substr ( $text, 2, 4 );
$data = substr ( $text, 6 );
}
$text = "";
for($i = 0; $i < strlen ( $data ); ++ $i) {
$text .= $data [$i] ^ $masks [$i % 4];
}
return $text;
}
// 编码数据。在服务器向客户端发送数据时需要将数据打包
function mask($text) {
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen ( $text );
if ($length <= 125) {
$header = pack ( 'CC', $b1, $length );
} elseif ($length > 125 && $length < 65536) {
$header = pack ( 'CCn', $b1, 126, $length );
} elseif ($length >= 65536) {
$header = pack ( 'CCNN', $b1, 127, $length );
}
return $header . $text;
} // 握手的逻辑。客户端与服务端相互识别的过程
function perform_handshaking($receved_header, $client_conn, $host, $port) {
$headers = array ();
$lines = preg_split ( "/\r\n/", $receved_header );
foreach ( $lines as $line ) {
$line = chop ( $line );
if (preg_match ( '/\A(\S+): (.*)\z/', $line, $matches )) {
$headers [$matches [1]] = $matches [2];
}
}
$secKey = $headers ['Sec-WebSocket-Key'];
$secAccept = base64_encode ( pack ( 'H*', sha1 ( $secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' ) ) );
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . "Upgrade: websocket\r\n" . "Connection: Upgrade\r\n" . "WebSocket-Origin: $host\r\n" . "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write ( $client_conn, $upgrade, strlen ( $upgrade ) );
}
php使用Socket实现聊天室功能(书中的代码)的更多相关文章
- [Python] socket发送UDP广播实现聊天室功能
一.说明 本文主要使用socket.socket发送UDP广播来实现聊天室功能. 重点难点:理解UDP通讯流程.多线程.UDP广播收发等. 测试环境:Win10\Python3.5. 程序基本流程:创 ...
- node+express+socket.io制作一个聊天室功能
首先是下载包: npm install express npm install socket.io 建立文件: 服务器端代码:server.js var http=require("http ...
- Socket.IO聊天室~简单实用
小编心语:大家过完圣诞准备迎元旦吧~小编在这里预祝大家元旦快乐!!这一次要分享的东西小编也不是很懂啊,总之小编把它拿出来是觉地比较稀奇,而且程序也没有那么难,是一个比较简单的程序,大家可以多多试试~ ...
- java基于socket公共聊天室的实现
项目:一个公共聊天室功能的实现,实现了登录聊天,保存聊天记录等功能. 一.实现代码 1.客户端 ChatClient.java import java.io.BufferedReader; impor ...
- Android 基于Socket的聊天室(一)
Socket是TCP/IP协议上的一种通信,在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路.一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信. Client A ...
- Netty学习笔记(四) 简单的聊天室功能之服务端开发
前面三个章节,我们使用了Netty实现了DISCARD丢弃服务和回复以及自定义编码解码,这篇博客,我们要用Netty实现简单的聊天室功能. Ps: 突然想起来大学里面有个课程实训,给予UDP还是TCP ...
- 使用epoll实现聊天室功能,同时比较epoll和select的异同
1.首先介绍一下select和epoll的异同,如下(摘抄自https://www.cnblogs.com/Anker/p/3265058.html) select的几大缺点: (1)每次调用sele ...
- Python Socket 编程——聊天室示例程序
上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和客户端的代码了解基本的 Python Socket 编程模型.本文再通过一个例子来加强一下对 Socket 编程的 ...
- Android进阶(十五)socket通信——聊天室
想做一个聊天室,花费了将近一天的时间,各种错误.讲解知识点之前,絮叨几句:动手能力还是很重要的,有时看似简单的一个问题,当你真正着手去解决的时候就有可能会遇到各种各样的问题,原因之一就是因为你的知识储 ...
随机推荐
- A1046
n个节点围成一个环,每个节点之间的距离已知.输入n并给出n个节点的距离,输入m组节点编号(两个),求这两个节点编号间的最短距离. 1 建立dis[]数组,记录V1点到每一个点的顺时针距离,sum计算环 ...
- 【微信小程序】setData的使用以及注意事项
Page.prototype.setData(Object data, Function callback) setData 函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.da ...
- Web应用防火墙云WAF详细介绍
Web应用防火墙,或叫Web应用防护系统(也称为:网站应用级入侵防御系统.英文:Web Application Firewall,简称: WAF).利用国际上公认的一种说法:Web应用防火墙是通过执行 ...
- C#知识点:委托、事件、正则表达式、SVN、找按段等差递增至不变序列的规律
using System; using System.Collections.Generic; using System.Text; namespace Delegate { //定义委托,它定义了可 ...
- 【bzoj2073】【[POI2004]PRZ】位运算枚举子集的特技
(上不了p站我要死了) Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一 ...
- [洛谷3934]P3934 Nephren Ruq Insania题解
先放个奈芙莲 解法 看到这种题目就知道是欧拉降幂,然后根据某玄学证明,递归欧拉降幂从l到r不会超过\(\Theta(log_n)\),所以直接递归解决,然后区间修改直接树状数组维护一下 然后就A了 代 ...
- CSS3实现图片黑白滤镜居中,hover缩放遮罩的效果
hover: 在前端开发中经常会遇到项目展示,往往会采用卡片方式来描述.众多网站中,普遍采用CSS3的scale()方法来实现交互. 本文即是利用纯CSS实现图片居中缩放,此类方法各大网站均有应 ...
- Linux shell - 修改文件所属用户和组 (chown, chgrp)
在工作中,会遇到这样的情况,需要把目录所属的的root用户更改到普通用户,root组更改到普通组. sha-q:/ # ll drwxr-xr-x 2 root root 4096 2014-09-1 ...
- mysql 无法远程连接 没有监听端口
centos yum安装mysql: 远程连接完成用户授权和防火墙配置,可还是连接不上. 发现mysql没有监听3306端口. 修改mysql配置文件 vi /etc/my.conf 注释掉以下行,重 ...
- [转]玩转Google开源C++单元测试框架Google Test系列(gtest)(总)
文章转载自CoderZh的技术博客 地址:https://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html 前段时间学习和了解了下Goog ...