1. The source of the problem
It has always been thought that the implementation of WebSocket is at the TCP protocol layer, which can be directly accessed javascript
by ws for communication.java
ServerSocket
- java side code
private ServerSocket serverSocket;
public void start(int port) throws IOException {
serverSocket = new ServerSocket(port);
System.out.println("server is running port " + port);
while (true) {
Socket sock = serverSocket.accept();
System.out.println("connected from " + sock.getRemoteSocketAddress());
new TcpClientHandler(sock).start();
}
}
- JavaScript code
const socket = new WebSocket('ws://localhost:8888/')
// Connection opened
socket.addEventListener('open', function (event) {
console.log('连接成功 ', event)
socket.send('Hello Server!')
})
The java side can accept the request normally, but it cannot handle it. At the same time, the js side reports a link error: From the error log, the request can reach the server side, but the handshake is not successful, and the client cannot receive the request. So the problem is not that simple, check the relevant information to learn.
2. Understanding WebSocket
WebSocket is an application layer protocol based on the TCP protocol, and multiplexes the handshake channel of HTTP to realize the network technology of full-duplex communication. It supports two-way communication. It is easy to use, you only need to call the API in the browser to complete the protocol switching. It also supports extensions and can implement custom sub-protocols in the protocol. Compared with the http protocol header overhead, it can be transmitted faster in the network.
Compared with the TCP protocol, WebSocket is relatively simple. It only needs to complete a get request and complete a protocol upgrade, so that WebSocket communication can be used.
Connection process:
ws://localhost:8888
Send get request, request protocol conversion, protocol header: Connection:Upgrade
Upgrade:websocket
, indicating protocol upgrade, upgrade protocol to websocket
. The code 101 returned by the server means that the protocol upgrade is successful, and the data can be transmitted through the two-way channel.
3. Example code
Java native code, the method of using Java native code to implement websocket service, this method needs to introduce a third-party library java-websocket.jar
The project source code is located at: github.com/TooTallNate…
Sample code at: github.com/TooTallNate…
If your project uses gradle as a management tool, you can add the following gradle dependencies
implementation group: 'org.java-websocket', name: 'Java-WebSocket', version: '1.5.3'
If your project is managed by maven, you can add the following maven dependencies
mven-dependency
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.3</version>
</dependency>
package com.mum.socket;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
public class SocketServer extends WebSocketServer {
public SocketServer(int port) throws UnknownHostException {
super(new InetSocketAddress(port));
}
public SocketServer(InetSocketAddress address) {
super(address);
}
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
conn.send("Welcome to the server!"); // This method sends a message to the new client
broadcast("new connection: " + handshake.getResourceDescriptor()); // This method sends a message to all clients
// connected
System.out.println(conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
broadcast(conn + " has left the room!");
System.out.println(conn + " has left the room!");
}
@Override
public void onMessage(WebSocket conn, String message) {
broadcast(message);
System.out.println(conn + ": " + message);
}
@Override
public void onError(WebSocket conn, Exception ex) {
ex.printStackTrace();
if (conn != null) {
// some errors like port binding failed may not be assignable to a specific
// websocket
}
}
@Override
public void onStart() {
System.out.println("Server started!");
//setConnectionLostTimeout(0);
setConnectionLostTimeout(100);
}
}
package com.mum.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class SocketServerTest {
public static void main(String[] args) throws InterruptedException, IOException {
int port = 8888; // 843 flash policy port
SocketServer s = new SocketServer(port);
s.start();
System.out.println("ChatServer started on port: " + s.getPort());
BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String in = sysin.readLine();
s.broadcast(in);
if (in.equals("exit")) {
s.stop(1000);
break;
}
}
}
}
js code implementation
<!DOCTYPE html>
<html lang="zh-CN">
<header>
<title>js code</title>
</header>
<style>
.container {
width: 100%;
position: relative;
}
.margintLeft10 {
margin-left: 10px;
}
</style>
<body>
<div class="container">
<button class="margintLeft10" onclick="socketTest()">socketTest</button>
<button class="margintLeft10" onclick="sendDate()">sendDate</button>
</div>
<script>
let socket;
function socketTest() {
socket = new WebSocket('ws://localhost:8888/')
// Connection opened
socket.addEventListener('open', function (event) {
console.log('连接成功 ', event)
socket.send('Hello Server!')
})
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server ', event.data)
})
// 监听错误事件
socket.addEventListener('error', function (event) {
console.log('error', event)
})
// 监听关闭事件
socket.addEventListener('close', function (event) {
console.log('close', event)
})
}
function sendDate() {
if (socket) {
socket.send('现在时间: ' + new Date());
} else {
console.log('socket 未创建');
}
}
</script>
</body>
</html>
node js实现更简单 借助 ws 库
const app = require("express")()
const server = require("http").Server(app)
const WebSocket = require("ws")
const MyWs = new WebSocket.Server({ port: 8080 })
MyWs.on("open", () => {
console.log("connected")
})
MyWs.on("close", () => {
console.log("disconnected")
})
MyWs.on("connection", (ws, req) => {
const port = req.connection.remotePort
const clientName = port
console.log(`${clientName} is connected`)
// 发送欢迎信息给客户端
ws.send("Welcome :" + clientName + "加入聊天室")
ws.on("message", (message) => {
// 广播消息给所有客户端
MyWs.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(clientName + " -> " + message)
}
})
})
})
app.get("/", (req, res) => {
res.sendfile(__dirname + "/index.html")
})
app.listen(8888)
参考资料
WebSocket:5分钟从入门到精通 juejin.cn/post/684490…
java实现websocket的五种方式 www.cnblogs.com/guoapeng/p/…