跳至主要內容
websocket

websocket

大约 5 分钟websocket网络websocket网络协议

websocket

websocket协议

WebSocket是一种网络通信协议,很多高级功能都需要它,例如浏览器与服务器之间的实时通信。

WebSocket协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。

WebSocket协议和HTTP协议都是应用层协议,都基于TCP协议。但是,WebSocket协议是一种双向通信协议,在建立连接后,WebSocket服务器和Browser/Client Agent都能主动向对方发送或接收数据,就像Socket一样;而HTTP协议是一种单向通信协议,只能由Client Agent向WebSocket服务器发送请求,WebSocket服务器不能主动向Client Agent发送数据,但是WebSocket服务器可以向Client Agent发送HTTP响应。

它的最大特点就是:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

WebSocket协议在建立握手时,数据是通过HTTP传输的,但是建立之后,在真正进行数据传输时,是不需要HTTP协议的,因此,WebSocket是一个独立的协议。

websocket的优势

WebSocket协议相比传统的HTTP协议有如下优势:

  • 支持双向通信,实时性更强;
  • 较少的控制开销。连接创建后,ws客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不包含头部的情况下,服务端到客户端的包头只有2~10字节(取决于数据包长度),客户端到服务端的的话,需要加上额外的4字节的掩码。而HTTP协议每次通信都需要携带完整的头部;
  • 支持扩展。ws协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议(例如支持自定义压缩算法等);
  • 更好的压缩效果。相比HTTP协议,Websocket协议中包头的数据量小很多;
  • 支持更多类型的数据。WebSocket定义了二进制帧,相比HTTP协议传输数据类型更多样化。

websocket的缺点

  • 需要服务器支持。因为需要服务器进行协议升级处理,所以需要服务器支持WebSocket协议;
  • 连接不能穿透防火墙。因为使用的是TCP协议,所以连接不能穿透防火墙;
  • 数据包头部比较大。每次通信都需要携带完整的头部,带宽占用较多。

websocket的应用场景

  • 聊天室
  • 网络游戏
  • 在线教育
  • 在线客服
  • 实时数据推送
  • 在线视频/音频会议
  • 在线多人协作开发
  • 在线多人实时协作办公

websocket的使用

建立连接

WebSocket协议本质上是一个基于TCP的协议,WebSocket连接在建立时需要借助HTTP协议,连接建立好后,底层的TCP连接就与HTTP无关了。

WebSocket连接的建立过程如下:

  1. 客户端向服务器发起一个HTTP请求,这个请求和通常的HTTP请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的HTTP请求,服务器端解析这些附加头信息,如果同意协议升级,则返回101状态码表示成功,表示协议已经升级,这时候TCP连接就升级为WebSocket连接了,后续的数据交换都按照WebSocket协议来进行,如果不同意协议升级,则返回4xx或5xx的状态码,表示协议升级失败,连接会按照HTTP协议来进行;

  2. 客户端和服务器端都可以在任意时刻发送数据,数据以帧(Frame)为单位传输,每个帧包含一定的数据以及标识信息,如数据是否被加密过、是否为控制帧等。

数据帧

WebSocket的不同类型的帧负责不同的功能,帧的类型如下:

  • 0x0:表示附加数据帧;
  • 0x1:表示文本数据帧;
  • 0x2:表示二进制数据帧;
  • 0x3-7:保留的数据帧类型;
  • 0x8:表示连接关闭;
  • 0x9:表示ping;
  • 0xA:表示pong;
  • 0xB-F:保留的控制帧类型。

数据帧的格式

WebSocket协议定义了数据帧的格式,如下图所示:

WebSocket数据帧格式
WebSocket数据帧格式

数据帧的格式如下:

  • FIN:1位,表示这是消息的最后一个数据帧;
  • RSV1, RSV2, RSV3:各1位,保留字段,暂时不使用;
  • Opcode:4位,表示数据帧的类型,如果是0x0表示附加数据帧,如果是0x1表示文本数据帧,如果是0x2表示二进制数据帧,如果是0x8表示连接关闭,如果是0x9表示ping,如果是0xA表示pong;
  • Mask:1位,表示是否要对数据进行掩码处理,从客户端向服务器端发送数据时,需要对数据进行掩码处理,从服务器端向客户端发送数据时,不需要对数据进行掩码处理;
  • Payload length:7位,表示数据的长度,如果是0~125,表示数据的长度,如果是126,表示后面2个字节表示数据的长度,如果是127,表示后面8个字节表示数据的长度;
  • Masking-key:4字节,如果Mask为1,表示掩码,否则为0;
  • Payload data:数据,长度等于Payload length。

WebSocket的使用

WebSocket的使用非常简单,只需要通过JavaScript的WebSocket对象即可,WebSocket对象的使用如下所示:

// 创建WebSocket对象
var ws = new WebSocket("ws://localhost:8080");

// 监听WebSocket的打开事件
ws.onopen = function() {
    console.log("WebSocket已经打开");
};

// 监听WebSocket的关闭事件

ws.onclose = function() {
    console.log("WebSocket已经关闭");
};

// 监听WebSocket的错误事件
ws.onerror = function() {
    console.log("WebSocket发生错误");
};

// 监听WebSocket的消息事件
ws.onmessage = function(event) {
    console.log("WebSocket接收到消息:" + event.data);
};

// 向WebSocket发送消息
ws.send("Hello WebSocket");

WebSocket的实现

WebSocket的实现非常简单,只需要使用Java的ServerSocket即可,ServerSocket的使用如下所示:

// 创建ServerSocket对象
ServerSocket serverSocket = new ServerSocket(8080);

// 监听客户端的连接
Socket socket = serverSocket.accept();

// 获取输入流
InputStream inputStream = socket.getInputStream();

// 获取输出流
OutputStream outputStream = socket.getOutputStream();

// 读取数据
byte[] buffer = new byte[1024];
int length = inputStream.read(buffer);
String data = new String(buffer, 0, length);
System.out.println("接收到数据:" + data);

// 发送数据
outputStream.write("Hello WebSocket".getBytes());

// 关闭连接
socket.close();
上次编辑于:
贡献者: uniqueli