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,期间还走过了一段"看似弯曲"的道路,但是我想其实也不算是弯路吧,因为你走过的路必将留下你的足迹.这 ...
随机推荐
- PreferenceActivity详解
为了引入这个概率 首先从需求说起 即:现有某Activity专门用于手机属性设置 那么应该如何做呢? 根据已学知识 很快一个念头闪过 即:Activity + Preference 组合 前者用于界面 ...
- MongoDB用户
MongoDB 增加用户 删除用户 修改用户 读写权限 只读权限, MongoDB用户权限分配的操作是针对某个库来说的.--这句话很重要. 1. 进入ljc 数据库: use ...
- 获取sql执行时间
sql server中获取要执行的sql或sql块的执行时间,方法之一如下: declare @begin datetime,@end datetime set @begin =getdate() - ...
- CSS3的一些前缀
为了兼容多个浏览器,css3通常前面加一大堆前缀 -webkit /*为Chrome/Safari*/-moz /*为Firefox*/-ms /*为IE*/-o /*为Opera*/ -w ...
- ubuntu apt-get update 连接不到指定的源
问题描述: ubuntu apt-get update 连接不到指定的源,修改了几个软件源还是连接不上,同样的软件源在别的机器上都可以正常使用,后来发现每次 sudo apt-get update操作 ...
- C# 实现屏幕键盘 (ScreenKeyboard)
原文地址:http://www.cnblogs.com/youzai/archive/2008/05/19/1202732.html 要实现一个屏幕键盘,需要监听所有键盘事件,无论窗体是否被激活.因此 ...
- hdu 5344 MZL's xor
MZL's xor Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- iOS高德地图自定义annotation添加不同图片
1.model类里面添加index #import <MAMapKit/MAMapKit.h> #import <AMapSearchKit/AMapCommonObj.h> ...
- 河南多校大一训练赛 E 开餐馆
题目链接:http://acm.hust.edu.cn/vjudge/contest/125004#problem/E 密码:acm Description 北大信息学院的同学小明毕业之后打算创业开餐 ...
- 转:LoadRunner常用函数列表
Web相关函数 函 数 功 能 描 述 web_custom_request 用户可以通过该函数自行创建一个HTTP请求的函数 web_image 模拟用户单击图片操作的函数 web_link ...