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 聊天室原理的更多相关文章

  1. HTML5新特性 websocket(重点)--多对多聊天室

    一.html5新特性  websocket(重点)--多对多聊天室 HTTP:超文本传输协议 HTTP作用:传输网页中资源(html;css;js;image;video;..) HTTP是浏览器搬运 ...

  2. Node.js+websocket+mongodb实现即时聊天室

    ChatRoom Node.js+websocket+mongodb实现即时聊天室 A,nodejs简介:Node.js是一个可以让javascript运行在服务器端的平台,它可以让javascrip ...

  3. nodejs与websocket模拟简单的聊天室

    nodejs与websocket模拟简单的聊天室 server.js const http = require('http') const fs = require('fs') var userip ...

  4. Java Socket聊天室编程(二)之利用socket实现单聊聊天室

    这篇文章主要介绍了Java Socket聊天室编程(二)之利用socket实现单聊聊天室的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在上篇文章Java Socket聊天室编程(一)之 ...

  5. Java Socket聊天室编程(一)之利用socket实现聊天之消息推送

    这篇文章主要介绍了Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 网上已经有很多利用socket实现聊天的例子了 ...

  6. Django中使用websocket并实现简易聊天室

    django使用websocket并实现简易聊天室 django默认只支持http协议 如果你想让django即支持http协议又支持websocket协议,则需要做以下配置 前期配置 前提需要安装c ...

  7. python socket 聊天室

    socket 发送的时候,使用的是全双工的形式,不是半双工的形式.全双工就是类似于电话,可以一直通信.并且,在发送后,如果又接受数据,那么在这个接受到数据之前,整个过程是不会停止的.会进行堵塞,堵塞就 ...

  8. TCP/IP以及Socket聊天室带类库源码分享

    TCP/IP以及Socket聊天室带类库源码分享 最近遇到个设备,需要去和客户的软件做一个网络通信交互,一般的我们的上位机都是作为客户端来和设备通信的,这次要作为服务端来监听客户端,在这个背景下,我查 ...

  9. 如何利用WebSocket实现网页版聊天室

    花了将近一周的时间终于完成了利用WebSocket完成网页版聊天室这个小demo,期间还走过了一段"看似弯曲"的道路,但是我想其实也不算是弯路吧,因为你走过的路必将留下你的足迹.这 ...

随机推荐

  1. 更改 android realtek的系统权限

    由于在 在删除系统的文件时候出现 Read-only file system,所以要获取权限. 推出shell adb mount mount -o rw,remount /system 就可以了

  2. Linq中max min sum avarage count的使用

    一.Max最大值 static void Main(string[] args) { //Max求最大值 ,,,,,,,,,}; //方法1 Linq语句+Linq方法 var result = (f ...

  3. Memcached 缓存服务器介绍

    1.memcached  高性能分布式内存对象缓存系统 2.目的:减轻数据库负载,提高基于动态数据库驱动网站的响应速度 3.数据格式:文本行 4.协议:memcache协议 5.存储方式:hashMa ...

  4. 一篇非常适合git入门的文章

    http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137583770360579 ...

  5. C#后台绑定ComboBox

    C# using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syste ...

  6. Notification使用笔记

    之前在项目中使用了Notification,现分享出来: checkNotification() function checkNotification(){ //判断是否支持Notification ...

  7. 转 Oracle DBCA高级玩法:从模板选择、脚本调用到多租户

    但凡是学过Oracle的同学,对DBCA(Database Configuration Assistant, DBCA)都不会陌生,有了这个工具,使得创建数据库成为可能.而DBCA本身有图形和静默两种 ...

  8. sh语法入门学习

    玩linux都知道sh脚本的方便,但如何编写sh脚本却是像我这样的新手和菜鸟的难题.能不能编写得出来是一回事,了不了解又是另一回事.抱着好好学习,天天向上的精神,大家有空就看看吧,没有坏处的.下面来抄 ...

  9. web项目docker化的两种方法

    标题所讲的两种方法其实就是创建docker镜像的两种方法 第一种:启动镜像后进入容器中操作,将需要的软件或者项目移动到容器中,安装或者部署,然后退出即可 第二种:编写dockerfile,将需要的镜像 ...

  10. WPF从我炫系列4---装饰控件的用法

    这一节的讲解中,我将为大家介绍WPF装饰控件的用法,主要为大家讲解一下几个控件的用法. ScrollViewer滚动条控件 Border边框控件 ViewBox自由缩放控件 1. ScrollView ...