socket php建立聊天室,如何使用php websocket创建简单聊天室

socket就是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。前面的章节我们谈到了socket和http的区别,要理解socket就要先理解http和tcp的区别,简单说就是一个是短链,一个是长链,一个是去服务器拉数据,一个是服务器可以主动推数据。http连接分为短连接和长连接。短连接一般可以用ajax实现,长连接就是websocket。短连接实现起来比较简单,但是太过于消耗资源。websocket高效不过兼容存在点问题。websocket是html5的资源。

php websocket创建简单聊天室流程介绍

php聊天室以前做时都是通过ajax与PHP来实现的,今天我们就一起来看一个PHP聊天室WebSocket技术实战例子.

1. 前台客户端

前台文件如何发送信息到后台服务器呢,后来研究发现是用的js 的WebSocket技术,如下是常用js WebSocket 常用操作:

其代码如下:var socket = new WebSocket('ws://localhost:8080');

// 打开Socket

socket.onopen = function(event) {

}

// 发送一个初始化消息

socket.send('I am the client and I\'m listening!');

// 监听消息

socket.onmessage = function(event) {

console.log('Client received a message',event);

}; //phpfensi.com

// 监听Socket的关闭

socket.onclose = function(event) {

console.log('Client notified socket has closed',event);

};

// 关闭Socket....

socket.close()

socket.onerror = function(evt){console.log(“WebSocketError!”);};

说明:第一行会向指定服务器发送一个握手请求,如果服务器返回合法的http头,则握手成功,之后可通过监听onmessage事件来处理服务器发来的消息。还有很多其他事件可监听,见前面的url。

2. 后台服务端

服务端做的流程大致是:

a. 挂起一个socket套接字进程等待连接

b. 有socket连接之后遍历套接字数组

c. 没有握手的进行握手操作,如果已经握手则接收数据解析并写入缓冲区进行输出

示例代码如下:public function start_server(){

$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

//允许使用本地地址

socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, TRUE);

socket_bind($this->socket, $this->host, $this->port);

//最多10个人连接,超过的客户端连接会返回WSAECONNREFUSED错误

socket_listen($this->socket, $this->maxuser);

while(TRUE) {

$this->cycle = $this->accept;

$this->cycle[] = $this->socket;

//阻塞用,有新连接时才会结束

socket_select($this->cycle, $write, $except, null);

foreach ($this->cycle as $k => $v) {

if($v === $this->socket) {

if (($accept = socket_accept($v)) < 0) {

continue;

}

//如果请求来自监听端口那个套接字,则创建一个新的套接字用于通信

$this->add_accept($accept);

continue;

}

$index = array_search($v, $this->accept);

if ($index === NULL) {

continue;

}

//没消息的socket就跳过

if (!@socket_recv($v, $data, 1024, 0) || !$data) {

$this->close($v);

continue;

}

if (!$this->isHand[$index]) {

$this->upgrade($v, $data, $index);

if(!empty($this->function['add'])) {

call_user_func_array($this->function['add'], array($this));

}

continue;

}

$data = $this->decode($data);

if(!empty($this->function['send'])) {

call_user_func_array($this->function['send'], array($data, $index, $this));

}

}

sleep(1);

}

}

//增加一个初次连接的用户

public function add_accept($accept){

$this->accept[] = $accept;

$index = array_keys($this->accept);

$index = end($index);

$this->isHand[$index] = FALSE;

}

//关闭一个连接

public function close($accept) {

$index = array_search($accept, $this->accept);

socket_close($accept);

unset($this->accept[$index]);

unset($this->isHand[$index]);

if(!empty($this->function['close'])) {

call_user_func_array($this->function['close'], array($this));

}

}

//响应升级协议

public function upgrade($accept, $data, $index) {

if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$data,$match)) {

$key = base64_encode(sha1($match[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));

$upgrade = "HTTP/1.1 101 Switching Protocol\r\n" .

"Upgrade: websocket\r\n" .

"Connection: Upgrade\r\n" .

"Sec-WebSocket-Accept: " . $key . "\r\n\r\n"; //必须以两个回车结尾

socket_write($accept, $upgrade, strlen($upgrade));

$this->isHand[$index] = TRUE;

}

}

说明:关键地方有那么几个,一是while(true)挂起进程,不然执行一次后进程就退出了。二是socket_select和socket_accept函数的使用。三是客户端第一次请求时握手。

后面的流程就很清晰了,当有一个新的客户端请求到达,用socket_accept创建一个资源,并加入到$this->accept连接池里面。并将它的标示isHand设为false,那么下次循环(因为$this->cycle[] = $this->socket;$this->cycle有变化,所以socket_select会返回)的时候就会执行upgrade握手。然后等待它的新消息即可。

【相关教程推荐】

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值