html5 WebSocket 与 PHP socket 聊天室原理
html js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>聊天室</title>
<link rel="stylesheet" href="css/style.css">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
</head>
<body>
<div class="head"></div>
<div id="wrapper">
<div id="message">
</div>
<div id="action">
<textarea id="data"></textarea>
<button id="send">发送</button>
</div>
</div>
<script>
(function() {
var socket = new WebSocket('ws://127.0.0.1:8008');
var send = document.getElementById('send');
var data = document.getElementById('data');
var message = document.getElementById('message');
var wrapper = document.getElementById('wrapper');
var height = (wrapper.offsetHeight) -270;
message.style.height = height+'px';
socket.onopen = function(event) {
message.innerHTML = '<p><span>连接成功!</span></p>';
}
socket.onmessage = function(event) {
var dl = document.createElement('dl');
var jsonData = JSON.parse(event.data);
dl.innerHTML = "<dt><img src="+jsonData.avatar+"><dt><dd><span></span>"+jsonData.content+"</dd>";
message.appendChild(dl);
message.scrollTop = message.scrollHeight;
}
socket.onerror = function() {
message.innerHTML = '<p><span>连接失败!</span></p>';
}
send.addEventListener('click', function() {
var content = data.value;
if(content.length <= 0) {
alert('消息不能为空!');
return false;
}
var avatar = Math.random();
var message = {
"avatar" : 'images/avatar.jpg',
"content" : content
}
var json = JSON.stringify(message);
socket.send(json);
data.value = ''; data.focus();
});
})();
</script>
</body>
</html>
PHP
<?php
class WebSocket {
private $socket;
private $accept;
private $isHand = array();
public function __construct($host, $port, $max) {
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, TRUE);
socket_bind($this->socket, $host, $port);
socket_listen($this->socket, $max);
}
public function start() {
while(true) {
$cycle = $this->accept;
$cycle[] = $this->socket;
socket_select($cycle, $write, $except, null);
foreach($cycle as $sock) {
if($sock === $this->socket) {
$client = socket_accept($this->socket);
$this->accept[] = $client;
$key = array_keys($this->accept);
$key = end($key);
$this->isHand[$key] = false;
} else {
$length = socket_recv($sock, $buffer, 204800, 0);
$key = array_search($sock, $this->accept);
if($length < 7) {
$this->close($sock);
continue;
}
if(!$this->isHand[$key]) {
$this->dohandshake($sock, $buffer, $key);
} else {
// 先解码,再编码
$data = $this->decode($buffer);
$data = $this->encode($data);
// 判断断开连接(断开连接时数据长度小于10)
if(strlen($data) > 10) {
foreach($this->accept as $client) {
socket_write($client, $data, strlen($data));
}
}
}
}
}
}
}
/**
* 首次与客户端握手
*/
public function dohandshake($sock, $data, $key) {
if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $data, $match)) {
$response = 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: " . $response . "\r\n\r\n";
socket_write($sock, $upgrade, strlen($upgrade));
$this->isHand[$key] = true;
}
}
/**
* 关闭一个客户端连接
*/
public function close($sock) {
$key = array_search($sock, $this->accept);
socket_close($sock);
unset($this->accept[$key]);
unset($this->handshake[$key]);
}
/**
* 解码过程
*/
public 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;
}
/**
* 编码过程
*/
public function encode($buffer) {
$length = strlen($buffer);
if($length <= 125) {
return "\x81".chr($length).$buffer;
} else if($length <= 65535) {
return "\x81".chr(126).pack("n", $length).$buffer;
} else {
return "\x81".char(127).pack("xxxxN", $length).$buffer;
}
}
}
$webSocket = new WebSocket('127.0.0.1', 8008, 100);
$webSocket->start();
?>
html5 WebSocket 与 PHP socket 聊天室原理的更多相关文章
- HTML5新特性 websocket(重点)--多对多聊天室
一.html5新特性 websocket(重点)--多对多聊天室 HTTP:超文本传输协议 HTTP作用:传输网页中资源(html;css;js;image;video;..) HTTP是浏览器搬运 ...
- Node.js+websocket+mongodb实现即时聊天室
ChatRoom Node.js+websocket+mongodb实现即时聊天室 A,nodejs简介:Node.js是一个可以让javascript运行在服务器端的平台,它可以让javascrip ...
- nodejs与websocket模拟简单的聊天室
nodejs与websocket模拟简单的聊天室 server.js const http = require('http') const fs = require('fs') var userip ...
- Java Socket聊天室编程(二)之利用socket实现单聊聊天室
这篇文章主要介绍了Java Socket聊天室编程(二)之利用socket实现单聊聊天室的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在上篇文章Java Socket聊天室编程(一)之 ...
- Java Socket聊天室编程(一)之利用socket实现聊天之消息推送
这篇文章主要介绍了Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 网上已经有很多利用socket实现聊天的例子了 ...
- Django中使用websocket并实现简易聊天室
django使用websocket并实现简易聊天室 django默认只支持http协议 如果你想让django即支持http协议又支持websocket协议,则需要做以下配置 前期配置 前提需要安装c ...
- python socket 聊天室
socket 发送的时候,使用的是全双工的形式,不是半双工的形式.全双工就是类似于电话,可以一直通信.并且,在发送后,如果又接受数据,那么在这个接受到数据之前,整个过程是不会停止的.会进行堵塞,堵塞就 ...
- TCP/IP以及Socket聊天室带类库源码分享
TCP/IP以及Socket聊天室带类库源码分享 最近遇到个设备,需要去和客户的软件做一个网络通信交互,一般的我们的上位机都是作为客户端来和设备通信的,这次要作为服务端来监听客户端,在这个背景下,我查 ...
- 如何利用WebSocket实现网页版聊天室
花了将近一周的时间终于完成了利用WebSocket完成网页版聊天室这个小demo,期间还走过了一段"看似弯曲"的道路,但是我想其实也不算是弯路吧,因为你走过的路必将留下你的足迹.这 ...
随机推荐
- php 控制循环
控制结构语法 endif.endswitch.endwhile.endfor.endforeach
- 理解Java String和String Pool
本文转载自: http://blog.sina.com.cn/s/blog_5203f6ce0100tiux.html 要理解 java中String的运作方式,必须明确一点:String是一个非可变 ...
- js连续赋值、指针
jq的源码中有很多连续赋值,类似这样的: var a = {n:1}; var b = a; // 持有a,以回查 a.x = a = {n:2}; alert(a.x);// --> unde ...
- jmx additional port
http://stackoverflow.com/questions/20884353/why-java-opens-3-ports-when-jmx-is-configured http://blo ...
- openCV(二)---iOS中使用openCV的图片格式转换
可以实现将UIImage和IplImage类型实现相互转换 //由于OpenCV主要针对的是计算机视觉方面的处理,因此在函数库中,最重要的结构体是IplImage结构. - (IplImage *)C ...
- 重写AlertView(用block)
@interface AlertView : UIView @property (nonatomic,copy) void(^block)(UIColor *color); - (id)initWit ...
- oracle登陆,在监听服务启动了的情况下,登陆用户还是报错未启动监听服务的错误(刚开始装oracle是能登陆的,重启之后装了plsql)
刚开始装oracle是能登陆的,重启之后装了140M的plsql,所以有可能是plsql跟oracle监听冲突了,所以我之后换了33M的plsql,oracle就没问题了,可以正常登陆了
- cssText笔记
style.cssText 用来获取/设置元素的样式 设置: <div id= "a" style= "background: red;"> doc ...
- 网站网址前的小logo
认识网页前小图标 1.能在浏览器标签.地址栏左边和收藏夹栏显示小图标的网站,其网站都是使用了其名称为"favicon.ico"图标文件,格式为ico格式,图标大小一般为16*16, ...
- layer属性
键: 值 描述 下表的属性都是默认值,您可在调用时按需重新配置,他们可帮助你实现各式各样的风格.如是调用: $.layer({键: 值, 键: 值, -}); type: 0 层的类型.0:信息框(默 ...