GeXiangDong

精通Java、SQL、Spring的拼写,擅长Linux、Windows的开关机

0%

websocket协议的连接过程

websocket协议的握手过程。
首先客户端和服务器端建立的是http 1.1的连接,客户端发送请求,请求的资源地址是websocket的地址,但在连接中增加几个请求头:

Connection: upgrade
Upgrade: Websocket
Sec-WebSocket-Key: base64格式的随机数
Sec-Websocket-Version: 13 (13是版本号)

服务器收到这种连接后,如果支持升级到websocket,会发出类似如下的回应:

HTTP/1.1 101 Switching Protocols
Server: Apache-Coyote/1.1
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: OfS0wDaT5NoxF2gqm7Zj2YtetzM=
Date: Tue, 04 Sep 2018 05:46:48 GMT

之后websocket连接就建好了,双方可以通讯了,下面有段建立连接的代码,可以参考。解析websocket帧部分没有写,只是当成字符串打印出来了,因为帧中包含一些二进制的控制信息,所以打印内容会有乱码(即使消息是纯文本也有乱码,因为有部分帧的头部信息也被当成字符串打印了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import java.net.*;
import java.io.*;

public class WebsocketClient {

public static void main(String[] args) throws Exception {

String hostname = "localhost";
int port = 8080;

try (Socket socket = new Socket(hostname, port)) {

OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);

writer.println("GET /chat HTTP/1.1");
writer.println("Host: " + hostname + ":" + port);
// 下面两行是告诉服务器端,此次连接的使用的http协议期望升级到websocket协议,如果服务端同意升级会返回
// Connection: upgrade upgrade: websocket表示已经升级了,而且状态吗是101 switching protocols
writer.println("Connection: upgrade");
writer.println("Upgrade: WebSocket");
// 下面这2行是必须的,sec-websocket-key是base64格式的一个随机数,由客户端生成
// sec-websocket-version是指明客户端的websocket版本
writer.println("Sec-WebSocket-Key: "AQIDBAUGBwgJCgsMDQ4PEC=" =");
writer.println("Sec-WebSocket-Version: 13");
writer.println("User-Agent: MSIE");
writer.println("Origin: http://localhost:8080/");
writer.println();

InputStream input = socket.getInputStream();

BufferedReader reader = new BufferedReader(new InputStreamReader(input));

System.out.println("request sent...");
int i=0;
while (i < 10) {
if (reader.ready()){
// 在读websocket发送过来的消息时,这里没有解码消息帧,都当字符串了,消息的数据报文格式前面有些事数据包控制的bit,所以打印时有乱码
char[] bin = new char[2048];
int len = reader.read(bin, 0, bin.length);
char[] buf = new char[len];
System.arraycopy(bin, 0, buf, 0, len);
System.out.println(new String(buf));
i++;
}
}
// 连接好了后可以发送数据,发送的数据报格式是 Base Framing Protocol, ABNF RFC5234
writer.close();
output.close();
socket.close();
} catch (UnknownHostException ex) {
System.out.println("Server not found: " + ex.getMessage());
} catch (IOException ex) {
System.out.println("I/O error: " + ex.getMessage());
}
}
}