WebSocket服务器工作逻辑大纲
一、主要目的
猜测WebSocket服务器主要的处理逻辑大纲。
二、WebSocket服务器主要逻辑
(一)循环接收TCP客户端连接
每个连接用一个线程处理。
// 监听80端口
ServerSocket s = new ServerSocket(80);
// 循环处理连接
while(true){
// 监听客户端
Socket client = s.accept();
// 创建线程
Task task = new Task(client);
// 启动线程
task.start();
}
(二)线程处理逻辑
1、客户端用HTTP的GET请求来握手。
2、服务端判断HTTP请求报文:
如果握手成功,设置Sec-WebSocket-Accept头部,返回101响应。
如果握手不成功,返回403响应。
3、握手成功后,用WebSocket格式来全双工通信。
主要逻辑如下:
// 线程子类Task
public class Task extends Thread{
// 引用套接字
private Socket s;
public Task(Socket s){
this.s = s;
}
// 描述线程逻辑
public void run(){
// 封装成Request对象
Request req = parseReq(s.getInputStream());
// 封装成Response对象
Response resp = parseResp(s.getOutputStream());
// 判断url路径为/chat和方法为GET
// 判断版本是13
if(req.getPath() == "/chat" && req.getMethod() == "GET" && req.getHead("Sec-WebSocket-Version") == "13"){
// 计算Sec-WebSocket-Accept值
// 获得请求头Sec-WebSocket-Key的值
String key = req.getHead("Sec-WebSocket-Key");
// 在后面拼接通用码
key = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
// 计算sha1摘要值
byte[] hash = Sha1Util.digest(key);
// 把摘要值转成base64格式字符串
String accept = Base64.encode(hash);
// 把结果设置到响应头
resp.setHead("Sec-WebSocket-Accept", accept);
// 握手成功,返回101
resp.setCode(101);
// 输出响应头
resp.outputHead();
// 开始循环WebSocket通信
loop(req.getInput(), resp.getOutput());
} else {
// 握手失败,返回403
resp.setCode(403);
// 输出响应头
resp.outputHead();
}
// 关闭套接字
s.close();
}
}
(三)监听WebSocket的数据包
// 循环方法
public void loop(InputStream in, OutputStream out) throws IOException{
// 建立事件处理对象
Listener listen = new Listener();
// 建立发送对象
Sender s = new Sender(out);
// 调用建立连接的方法
listen.open(s);
// 循环处理
while(true){
// 读取一个WebSocket数据包
Data d = readData(in);
// 判断操作码类型
if(d.getOpcode() == 1){
// 类型为1是文本数据
// 调用事件监听器的data()方法
// 转成UTF-8字符串
listen.data(s,
new String(d.getBody(), "UTF-8"));
} else if(d.getOpcode() == 2){
// 类型为2,是二进制类型
// 调用监听器的bindata()方法
listen.bindata(s, d.getBody());
} else if(d.getOpcode() == 8) {
// 类型为8是客户端主动关闭
// 调用监听器的close()方法
listen.close(s);
// 跳出循环
break;
}
}
}
说明:WebSocket数据包操作码值为1是文本类型,值为2是二进制类型,值为8是对方主动关闭。
读者可以处理其他的数据包类型。
(四)事件处理器的方法
public class Listener{
// 处理打开事件
public void open(Sender sender){
System.out.println("新连接");
}
// 处理字符串数据接受事件
public void data(Sender s, String str){
// 打印收到的字符串信息
System.out.println("接收结果:" + str);
// 服务器回复
s.sendText("我是服务器,收到了");
}
// 处理接收二进制数据
public void bindata(Sender s, byte[] array){
// 存储或者处理二进制数据
}
// 处理关闭事件
public void close(Sender s){
// 关闭输出
s.close();
}
}
三、总结
1、本文只是大概介绍WebSocket服务器的处理逻辑。
2、本文的WebSocket服务器绑定在HTTP的"/chat"资源路径,实际需要用户自己修改。
3、WebSocket数据包的读取解析和发送打包比较复杂,需要读者自己钻研。
例如:判断负载数据的长度,计算数据的掩码。
4、本文没有提供一些获取URL路径参数的方法。
5、本文没有为每个连接创建会话信息。
需要自定义一个会话类,指定Socket属性。
更多推荐


所有评论(0)