WebSocket and Java native communication

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 javascriptby ws for communication.javaServerSocket

  • 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.

image.png

image.png

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.

image.png

Connection process:

ws://localhost:8888Send 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.

image.png

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/…

Guess you like

Origin juejin.im/post/7250377976134451257