WebSocket 客户端使用教程(后续会更新服务端教程)

简介

WebSocket是一种实时推送技术,可以实现在线聊天,数据实时传输等功能。WebSocket是 HTML5 的一种新的协议,它实现了浏览器和服务器的全双工通信(full-duplex),一开始的握手需要借助 http 完成。
他是一个单个在 tcp 连接上建立全双工通讯协议,
全双工:同时双向传输数据
单工:同一时间内只能发生一个动作。

http 协议和 webscoket 的区别
在这里插入图片描述
http请求一次服务器回答一次,webSocket请求一次就会建立一个双向通道,服务端可以主动推送消息给浏览器端。

其最大的特点:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

使用

1.1 语法

var ws=new WebSocket("ws://localhost:8080",[protocols]);

protocols :可选,可以不写,表示WebSocket指定的子协议

抛出异常:
SECURITY_ERR:尝试连接的端口被阻止
SyntaxError:网址无效

1.2 目前支持的浏览器

谷歌,火狐,Opera,Edge,Android,Samsung Internet

1.3 webSocket.readyState 常数

WebSocket.CONNECTING 值:0,表示正在连接。
WebSocket.OPEN 值:1,表示连接成功,可以通信了。
WebSocket.CLOSING 值:2,表示连接正在关闭。
WebSocket.CLOSED 值:3,表示已关闭或者打开连接失败。

小示例:

switch (ws.readyState) {
  case WebSocket.CONNECTING:
    // do something
    break;
  case WebSocket.OPEN:
    // do something
    break;
  case WebSocket.CLOSING:
    // do something
    break;
  case WebSocket.CLOSED:
    // do something
    break;
  default:
    // this never happens
    break;
}

1.4 Properties 属性

WebSocket.binaryType
连接使用的二进制数据类型。
WebSocket.bufferedAmount 只读
排队数据的字节数。
WebSocket.extensions 只读
服务器选择的扩展名。
WebSocket.onclose
连接关闭时要调用的事件侦听器。
WebSocket.onerror
发生错误时将调用事件侦听器。
WebSocket.onmessage
从服务器收到消息时要调用的事件侦听器。
WebSocket.onopen
打开连接时要调用的事件侦听器。
WebSocket.protocol 只读
服务器选择的子协议。
WebSocket.readyState 只读
连接的当前状态。
WebSocket.url 只读
WebSocket的绝对URL

1.5 WebSocket.close() 关闭连接

该WebSocket.close()方法关闭WebSocket连接或连接尝试(如果有)。如果连接已经存在CLOSED,则此方法不执行任何操作。

1.5.1 参数

code 可选
指示状态代码的数字值,用于解释为什么关闭连接。如果未指定此参数,则默认值为1005(没有收到状态)。
reason 可选
表示连接为何关闭的字符串,该字符串不得超过123个字节的UTF-8文本(非字符)。

1.5.2 异常

INVALID_ACCESS_ERR:code指定无效
SYNTAX_ERR:该reason字符串过长或者无效
注意:在Gecko中,此方法在Gecko 8.0之前(Firefox 8.0 / Thunderbird 8.0 / SeaMonkey 2.5)不支持任何参数。

1.6 WebSocket.send(data) 使要发送的数据入队

该WebSocket.send()方法使要通过WebSocket连接传输到服务器的指定数据排队,从而将的值增加了bufferedAmount包含数据所需的字节数。如果无法发送数据(例如,由于需要缓冲但缓冲区已满),则套接字将自动关闭。

1.6.1 语法

WebSocket.send(“Hello server!”)

1.6.2 参数类型 data

USVString
文本字符串。字符串以UTF-8格式添加到缓冲区,并且值bufferedAmount增加代表UTF-8字符串所需的字节数。

ArrayBuffer
可以发送类型化数组对象使用的底层二进制数据;它的二进制数据内容在缓冲区中排队,按所需的字节数增加bufferedAmount的值。

Blob
指定一个值Blob会使Blob的原始数据排队进入二进制帧。的值bufferedAmount增加该原始数据的字节大小。

ArrayBufferView
你可以发送任何JavaScript类型的数组对象作为二进制帧;它的二进制数据内容在缓冲区中排队,按所需的字节数增加bufferedAmount的值。

1.6.3 可以对响应数据类型做判断
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');

// handle Received Message event
socket.onmessage = function(event) {
  if(typeof event.data === USVString){
  	console.log("Received data USVString");
  }
  if(event.data instanceof ArrayBuffer){
  	var buffer = event.data;
  	console.log("Received data ArrayBuffer"+buffer.typeLength);
  }
  if(typeof event.data === Blob){
  	console.log("Received data Blob");
  }
  if(event.data instanceof ArrayBufferView){
  	var bufferview = event.data;
  	console.log("Received data ArrayBufferView");
  }
};

//发送 blod 对象的例子
var file = document
  .querySelector('input[type="file"]')
  .files[0];
ws.send(file);
//发送 ArrayBuffer 对象的例子
// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
  binary[i] = img.data[i];
}
ws.send(binary.buffer);
异常

INVALID_STATE_ERR:当前没有连接OPEN。
SYNTAX_ERR: 数据是具有未配对替代的字符串。

1.7 addEventListener() 事件

使用addEventListener()或通过将事件侦听器分配给此接口的属性来侦听这些事件.

close
当与a的连接WebSocket关闭时触发。
也可以通过onclose属性使用

error
当WebSocket由于错误而与a的连接已关闭(例如无法发送某些数据)时触发。
也可通过onerror属性获得。

message
通过接收数据时触发WebSocket。
也可通过onmessage属性获得。

open
当一个WebSocket连接被打开时触发。
也可通过onopen属性获得。

当然还有onclose(),onmessage(),onopen()方法可以使用

示例
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');

// handle open event
socket.open = function(event) {
	console.log(event.data);
	socket.send("Hello,World!")
};
// handle Received Message event
socket.onmessage = function(event) {
  console.log( "Received Message: " + event.data);
  socket.close();
};
// Connection opened
socket.addEventListener('open', function (event) {
    socket.send('Hello Server!');
});

1.8 webSocket.bufferedAmount()

实例对象的bufferedAmount属性,表示还有多少字节的二进制数据没有发送出去。它可以用来判断发送是否结束。

var data = new ArrayBuffer(10000000);
socket.send(data);

if (socket.bufferedAmount === 0) {
  // 发送完毕
} else {
  // 发送还没结束
}

更多资料:

阮一峰大神笔记

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于 Hyperf WebSocket 服务端的鉴权,你可以在 onHandShake 方法中进行实现,该方法WebSocket 握手阶段触发。具体实现步骤如下: 1. 在 config/autoload 文件夹下创建一个 auth.php 配置文件,用于存储需要鉴权的用户信息。例如: ``` <?php return [ 'users' => [ [ 'username' => 'user1', 'password' => 'password1', ], [ 'username' => 'user2', 'password' => 'password2', ], ], ]; ``` 2. 在 WebSocket 控制器的 onHandShake 方法中获取客户端发送的参数(如用户名和密码),并与 auth.php 中存储的用户信息进行比对。如果验证通过,则保存用户信息到 WebSocket 的上下文中,以便后续操作使用。例如: ``` <?php declare(strict_types=1); namespace App\Controller; use Hyperf\WebSocketServer\Context; use Hyperf\WebSocketServer\Sender; use Hyperf\WebSocketServer\Annotation\WebSocket; use Hyperf\WebSocketServer\Contract\RequestInterface; use Hyperf\WebSocketServer\Contract\ResponseInterface; /** * @WebSocket */ class AuthController { public function onHandShake(RequestInterface $request, ResponseInterface $response): void { $username = $request->get('username'); $password = $request->get('password'); // 从配置文件中获取用户信息 $users = config('auth.users', []); // 验证用户信息 foreach ($users as $user) { if ($user['username'] === $username && $user['password'] === $password) { // 验证通过,保存用户信息到上下文中 Context::set('user', $user); return; } } // 验证失败,关闭 WebSocket 连接 $sender = make(Sender::class, ['response' => $response]); $sender->close(); } } ``` 3. 在其他 WebSocket 控制器的方法中,可以通过 Context::get('user') 获取已经鉴权的用户信息,进行后续操作。例如: ``` <?php declare(strict_types=1); namespace App\Controller; use Hyperf\Di\Annotation\Inject; use Hyperf\WebSocketServer\Context; use Hyperf\WebSocketServer\Annotation\WebSocket; /** * @WebSocket */ class ChatController { /** * @Inject * @var \Hyperf\WebSocketServer\Sender */ protected $sender; public function onMessage($fd, $data) { $user = Context::get('user'); if (! $user) { // 用户未鉴权,无法进行操作 return; } // 用户已鉴权,进行后续操作 // ... } } ``` 通过以上步骤,你就可以在 Hyperf WebSocket 服务端实现用户鉴权。当然,具体实现方式可以根据自己的业务需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值