如何构建一个 websocket HttpHandler [英] How to build a websocket HttpHandler

查看:65
本文介绍了如何构建一个 websocket HttpHandler的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 HttpServer 上使用 websockets.这是我想出的 HttpHandler ... 和相应的 EchoServer

I'd like to use websockets with at HttpServer. Here is the HttpHandler I came up with ... and the corresponding EchoServer

public class WebSocketHandler implements HttpHandler {

    @Override
    public void handle(final HttpExchange exchange) throws IOException {
        String requestMethod = exchange.getRequestMethod();
        if (requestMethod.equalsIgnoreCase("GET")) {
            System.out.println("Well formed websocket Upgrade request");
            /*
             * HTTP/1.1 101 Switching Protocols
             * Upgrade: websocket
             * Connection: Upgrade
             * Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
             * ''Sec-WebSocket-Protocol: chat
             */

            Headers responseHeaders = exchange.getResponseHeaders();
            responseHeaders.set("Upgrade", "websocket");
            responseHeaders.set("Connection", "Upgrade");
            responseHeaders.set("Sec-WebSocket-Accept", "XXXX");
            exchange.sendResponseHeaders(101, 0);
            exchange.getResponseBody().write("ok".getBytes());
            ServerEndpointConfig.Builder.create(EchoServer.class, "/echo").build();
        } else {
            System.out.println("Server: non-GET websocket upgrade request....");
            exchange.sendResponseHeaders(200, 0);
            exchange.getResponseBody().write("ok".getBytes());
        }

    }
}

EchoServer 类是:

The EchoServer class is:

@ServerEndpoint(value = "/echo")
public class EchoServer {

    private Logger logger = Logger.getLogger(this.getClass().getName());
    int id = 0;

    @OnOpen
    public void onOpen(Session session) {
        logger.info("Connected ... " + session.getId());
    }

    @OnMessage
    public String onMessage(String message, Session session) {
        switch (message) {
            case "quit":
                try {
                    session.close(new CloseReason(CloseCodes.NORMAL_CLOSURE, "Game ended"));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                break;
        }
        id++;
        return String.format("%d:%s", id, message);
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        logger.info(String.format("Session %s closed because of %s", session.getId(), closeReason));
    }
}

我不太希望这会奏效,因为我认为连接 ID 不会被交换.

I don't have much hope that this will work because I don't think the connection IDs are exchanged.

您将如何完成此代码以获得功能性的 websocket 连接?

How would you complete this code to get a functional websocket connection?

推荐答案

com.sun.net.httpserver.HttpExchange 用于 WebSocket 是行不通的.

Using com.sun.net.httpserver.HttpExchange for WebSocket isn't going to work.

该 API 不允许真正升级的连接.换句话说,一个没有 HTTP 连接编码或封装的连接(例如 chunked 或 gziped 等)

That API for that doesn't allow for a true upgraded connection. In other words, a connection where there is no HTTP connection encoding or encapsulation (such as chunked, or gziped, etc)

此外,您对 WebSocket 升级的协议处理无效,没有浏览器会发现该响应有效并继续升级.

Also, your protocol handling of the WebSocket upgrade isn't valid, no browser out there will find that response to be valid and continue the upgrade.

代码中有 2 个示例.

2 examples in your code.

  • Sec-WebSocket-Accept 必须提供,并根据传入的请求头正确计算
  • Sec-WebSocket-Protocol 必须提供,如果传入的请求定义了一个
  • Sec-WebSocket-Accept must be provided, and be correctly calculated from the incoming request headers
  • Sec-WebSocket-Protocol must be provided, if the incoming request has one defined

这篇关于如何构建一个 websocket HttpHandler的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆