websocket服务器+客户端
<?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服务器+客户端的更多相关文章
- 开源的C#实现WebSocket协议客户端和服务器websocket-sharp组件解析
很久没有写博客了(至少自己感觉很长时间没有写了),没办法啊,楼主也是需要生活的人啊,这段一直都在找工作什么的.(整天催我代码的人,还望多多谅解啊,我会坚持写我们的项目的,还是需要相信我的,毕竟这是一个 ...
- C#实现WebSocket协议客户端和服务器websocket sharp组件实例解析
看到这篇文章的题目,估计很多人都会问,这个组件是不是有些显的无聊了,说到web通信,很多人都会想到ASP.NET SignalR,或者Nodejs等等,实现web的网络实时通讯.有关于web实时通信的 ...
- HTTPS请求HTTP接口被浏览器阻塞,python实现websocket客户端,websocket服务器,跨域问题,dwebsocket,https,拦截,服务端
HTTPS请求HTTP接口被浏览器阻塞,python实现websocket客户端,websocket服务器,跨域问题,dwebsocket,https,拦截,服务端 发表时间:2020-03-05 1 ...
- HTML5学习总结-08 WebSocket 服务器推送
一 WebSocket 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展 ...
- WebSocket 服务器4
Java Websocket实例 Websocket 2015-04-11 14:11:54 发布 您的评价: 4.4 收藏 6收藏 介绍 现很多网站为了实现即时通讯,所用 ...
- 根据Unix哲学来编写你的HTML5 Websocket服务器来实现全双工通信
websocketd代表WebSocket的守护进程 websocketd处理的是浏览器和服务器之间的WebSocket连接,它会启动你所指定的服务器端应用来对WebSockets进行处理,然后在浏览 ...
- 实现一个websocket服务器-理论篇
本文是Writing WebSocket servers的中文文档,翻译自MDNWriting WebSocket servers.篇幅略长,个人能力有限难免有所错误,抛砖引玉共同进步. websoc ...
- 如何实现websocket服务器-理论篇
WebSocket 服务器简单来说就是一个遵循特殊协议监听服务器任意端口的tcp应用.搭建一个定制服务器的任务通常会让让人们感到害怕.然而基于实现一个简单的Websocket服务器没有那么麻烦. 一个 ...
- node实现一个WEBSOCKET服务器
早点时候翻译了篇实现一个websocket服务器-理论篇,简单介绍了下理论基础,本来打算放在一起,但是感觉太长了大家可能都看不下去.不过发现如果拆开的话,还是不可避免的要提及理论部分.用到的地方就简要 ...
随机推荐
- Ambari搭建hadoop错误记录
1.ResourceManager启动失败 错误如下 2019-03-24 19:57:00,607 - Error while executing command 'start': Tracebac ...
- SDR软件无线电知识要点(三)EVM
SDR软件无线电知识要点(三)EVM 信号质量如何评估 Noise Figure (NF) or sensitivity and Error Vector Magnitude (EVM) provid ...
- 【C】对指针表达式的个人总结与思考
本文内容参考<c 和 指针>. 声明:本博文只为那些能沉得住气,认真研究,探索真知的人参考,浮躁的人请离开,因为看不懂. 感觉以前学c的时候,学的指针真是白学了,今天看到这个内容,困惑后, ...
- 【常用】IDEA常用快捷键与操作
以下出场顺序为开始学习IDEA时遇到的顺序,并非实际中的使用频率,最终版待整理 0.“ctrl+space(由于习惯问题我已经更改为alt+/)”——基本提示 “ctrl+shift+space”—— ...
- 20155310第一周JAVA实验报告
20155310第一周JAVA实验报告 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 实验要求 使用JDK和IDE编译.运行简单 ...
- C语言复习20170716
C语言复习20170716 C数据类型 图片来自:C语言基本数据类型简介 C语言程序处理的数据有常量和变量两种形式. 常量是在程序中不能改变其值的量.例如:整型常量.实型常量.字符常量.字符串常量和枚 ...
- [BZOJ2127]happiness-[网络流-最小割]
Description 传送门 Solution 按照最小割的思路考虑. 根据题意,当两个人都选文(理),需要砍掉两个人都选理(文)的加成:如果两个人选的不一样,就要都砍掉. 这是一个网络流建模的套路 ...
- 【Loj10222】佳佳的Fibonacci
题面 题解 可以发现\(T(n)\)无法用递推式表示. 于是我们做如下变形: \[ T(n) = \sum _ {i = 1} ^ n i \times f_i \\ S(n) = \sum _ {i ...
- 【LG3234】[HNOI2014]抄卡组
题面 题解 分三种情况: 若所有串都没有通配符,直接哈希比较即可. 若所有串都有通配符, 把无通配符的前缀 和 无通配符的后缀哈希后比较即可. 中间部分由于通配符的存在,一定可以使所有串匹配. 若部分 ...
- php S3调用SDK示例 AmazonS3
demo.php <?php /* * To change this license header, choose License Headers in Project Properties. ...