<?php
$demo = new ws('192.168.90.47',12345);
$demo->run(); class ws
{
//当前服务端主连接
private $currentFirstSocket;
//存放客户端socket连接
private $socketList = array();
//存放自定义的客户端连接
private $clientList = array(); public function __construct($address, $port)
{
$this->currentFirstSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($this->currentFirstSocket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($this->currentFirstSocket, $address, $port);
socket_listen($this->currentFirstSocket,2); $this->socketList[] = $this->currentFirstSocket;
self::notice('Server Started ...');
self::notice('Listening on : ' . $address . ' port ' . $port);
} public function run()
{
while (TRUE) {
$connect = $this->socketList;
$write = NULL;
$except = NULL;
self::notice(count($this->socketList) . " wait to connect ....");
socket_select($connect, $write, $except, NULL); foreach ($connect as $currentConnect) {
self::notice($currentConnect . " into connect"); //第一次连接
if ($currentConnect === $this->currentFirstSocket) {
$connectSuccessHandle = socket_accept($this->currentFirstSocket);
$this->socketList[] = $connectSuccessHandle;
$this->clientList[] = array(
"handshake" => false,
"clientHandle" => $connectSuccessHandle
);
self::notice($connectSuccessHandle. " new connect success ...");
} else {
$currentConnectKey = $this->searchSocketByHandle($currentConnect);
//第二次接收到的是客户端发送的websocket头协议
$len = @socket_recv($currentConnect, $buffer, 2048, 0);
self::notice("len ".$len);
if ($len < 10) { //如果接收到的信息长度小于10当作客户端退出
$this->socketExit($currentConnectKey);
self::notice($currentConnect . " exit" . " have:" . count($this->socketList));
break;
}
//检查是否握手,去握手
if ($this->clientList[$currentConnectKey]['handshake'] === false) {
self::notice($currentConnect." handshake success...");
$this->handshake($currentConnectKey, $buffer);
} else {
//正式连接,解包客户端的信息
$buffer = $this->unmask($buffer);
self::notice($currentConnect." send to server..."); $this->send($buffer);
}
}
}
}
} /*
* 握手
* */
private function handshake($currentConnectKey, $buffer)
{
$buf = substr($buffer, strpos($buffer, 'Sec-WebSocket-Key:') + 18);
$key = trim(substr($buf, 0, strpos($buf, "\r\n")));
$new_key = base64_encode(sha1($key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
$new_message = "HTTP/1.1 101 Switching Protocols\r\n";
$new_message .= "Upgrade: websocket\r\n";
$new_message .= "Sec-WebSocket-Version: 13\r\n";
$new_message .= "Connection: Upgrade\r\n";
$new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n"; socket_write($this->clientList[$currentConnectKey]['clientHandle'], $new_message, strlen($new_message));
$this->clientList[$currentConnectKey]['handshake'] = true;
} /*
* 客户端退出处理
* */
private function socketExit($currentConnectKey)
{
$currentSocket = $this->clientList[$currentConnectKey]['clientHandle'];
socket_shutdown($currentSocket);
socket_close($currentSocket);
foreach ($this->socketList as $key => $val) {
if ($val === $currentSocket) {
self::notice("delete " . $this->socketList[$key]);
unset($this->socketList[$key]);
}
}
unset($this->clientList[$currentConnectKey]);
} /*
* 发送信息给所有客户端
* */
private function send($sendMsg)
{
$sendMsg = $this->mask($sendMsg);
foreach ($this->clientList as $val) {
self::notice("write to " . $val['clientHandle'] . " " . $sendMsg);
socket_write($val['clientHandle'], $sendMsg, strlen($sendMsg));
}
} /*
* 解包客户端发送的信息
* */
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;
} private function searchSocketByHandle($handle)
{
foreach ($this->clientList as $key => $value) {
if ($value['clientHandle'] === $handle) {
return $key;
}
}
return false;
} private static function notice($message, $num = 1)
{
echo date("H:i:s") . " " . $message;
echo str_repeat("\n", $num);
}
}

客户端

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>client</title>
<script src="bootstrap/js/jq.js"></script>
<script>
var socket;
$(document).ready(function(e) {
connect();
}); function connect(){
var url='ws://192.168.174.132:12345';
socket = new WebSocket(url);
socket.onopen=function(){
if(socket.readyState==1){
socket.send("hello this is html");
}else{
console.log("login fail");
}
}
socket.onmessage=function(msg){
console.log(msg);
} socket.onclose=function(){
console.log("close");
}
} function sendMsg()
{
var contetent = $("#test").val();
console.log("send: "+contetent);
socket.send(contetent);
} </script>
</head>
<body> <input type="input" id="test">
<input type="button" onclick="sendMsg()" value="send"> </body>
</html>

websocket服务器+客户端的更多相关文章

  1. 开源的C#实现WebSocket协议客户端和服务器websocket-sharp组件解析

    很久没有写博客了(至少自己感觉很长时间没有写了),没办法啊,楼主也是需要生活的人啊,这段一直都在找工作什么的.(整天催我代码的人,还望多多谅解啊,我会坚持写我们的项目的,还是需要相信我的,毕竟这是一个 ...

  2. C#实现WebSocket协议客户端和服务器websocket sharp组件实例解析

    看到这篇文章的题目,估计很多人都会问,这个组件是不是有些显的无聊了,说到web通信,很多人都会想到ASP.NET SignalR,或者Nodejs等等,实现web的网络实时通讯.有关于web实时通信的 ...

  3. HTTPS请求HTTP接口被浏览器阻塞,python实现websocket客户端,websocket服务器,跨域问题,dwebsocket,https,拦截,服务端

    HTTPS请求HTTP接口被浏览器阻塞,python实现websocket客户端,websocket服务器,跨域问题,dwebsocket,https,拦截,服务端 发表时间:2020-03-05 1 ...

  4. HTML5学习总结-08 WebSocket 服务器推送

    一 WebSocket 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展 ...

  5. WebSocket 服务器4

    Java Websocket实例 Websocket   2015-04-11 14:11:54 发布 您的评价:       4.4   收藏     6收藏 介绍 现很多网站为了实现即时通讯,所用 ...

  6. 根据Unix哲学来编写你的HTML5 Websocket服务器来实现全双工通信

    websocketd代表WebSocket的守护进程 websocketd处理的是浏览器和服务器之间的WebSocket连接,它会启动你所指定的服务器端应用来对WebSockets进行处理,然后在浏览 ...

  7. 实现一个websocket服务器-理论篇

    本文是Writing WebSocket servers的中文文档,翻译自MDNWriting WebSocket servers.篇幅略长,个人能力有限难免有所错误,抛砖引玉共同进步. websoc ...

  8. 如何实现websocket服务器-理论篇

    WebSocket 服务器简单来说就是一个遵循特殊协议监听服务器任意端口的tcp应用.搭建一个定制服务器的任务通常会让让人们感到害怕.然而基于实现一个简单的Websocket服务器没有那么麻烦. 一个 ...

  9. node实现一个WEBSOCKET服务器

    早点时候翻译了篇实现一个websocket服务器-理论篇,简单介绍了下理论基础,本来打算放在一起,但是感觉太长了大家可能都看不下去.不过发现如果拆开的话,还是不可避免的要提及理论部分.用到的地方就简要 ...

随机推荐

  1. (补题 杭电 1008)Elevator

    Elevator Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  2. Python学习之——Python安装

    环境:Centos6.5+python2.7.5 1.centons6.5系统中是已经安装了python的,先查看版本是不是需要的 python --version 2.安装一些必要的包,防止后面需要 ...

  3. scala (8) 模糊匹配

    object MatchDemo { /** * 定义偏函数用PartialFunction来表示 * PartialFunction[T1,T2]要求传入一个参数T1,T2代表返回的类型. * 偏函 ...

  4. 20155236 《Java程序设计》实验二实验报告

    20155236 <Java程序设计>实验一(Java开发环境的熟悉)实验报告 一.实验内容及步骤 实验内容 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装.继承.多态 ...

  5. 学号20155311 2016-2017-2 《Java程序设计》第一次实验报告

    课程:Java程序设计 实验名称:Java开发环境的熟悉 实验目的与要求: 没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑器> 课程: 完成实验. ...

  6. 优步uber司机常见问题与答案(成都地区官方)

    成都地区优步司机常见问题,官方内容,有点多,常出现的问题都收录在这里了,大家可以看看.(注:文章转自官方,非原创) 以下为成都优步合作车主最常见的问题列表和答案.对于绝大多数的车主端问题,您都可以在下 ...

  7. 数据结构思维导图 Part1

    刚刚结束数据结构的学习,在复习阶段,所以做来思维导图总结一下. 思维导图,顾名思义是应该有对思维有引导作用的,就像思维的整理术,然而想要学好什么,光看思维导图总是不够的. 树与图作为两个复杂非线性结构 ...

  8. (treap)[bzoj3224][洛谷3369][cogs1829]Tyvj 1728 普通平衡树

    Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...

  9. L018-crond的生产场景经验小节

    L018-crond的生产场景经验小节 怎么说呢,其实L018这节课还是巩固crond的知识,前半堂课主要是解决上堂课老师留的作业(在L017已经更新,拉到最后),然后剩下的半堂客主要是讲解了一些生产 ...

  10. javaweb(三十四)——使用JDBC处理MySQL大数据

    一.基本概念 大数据也称之为LOB(Large Objects),LOB又分为:clob和blob,clob用于存储大文本,blob用于存储二进制数据,例如图像.声音.二进制文等. 在实际开发中,有时 ...