Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用单个Java ServerSocket读取安全web请求并处理web套接字请求?_Java_Server - Fatal编程技术网

如何使用单个Java ServerSocket读取安全web请求并处理web套接字请求?

如何使用单个Java ServerSocket读取安全web请求并处理web套接字请求?,java,server,Java,Server,简介 我的代码可以处理发送到服务器的所有字节,并决定是否让它们通过并最终发送响应。我想使用它将服务器作为web服务器、web套接字服务器和tcp服务器结合使用 虽然我的代码是为Minecraft编写的,但我并不是在Minecraft论坛上问这个问题,因为回答这个问题并不需要事先了解Minecraft或其代码库 有关Minecraft的所有您需要了解的信息 Minecraft是一款可以在线玩的Java游戏。在线播放时,有一台服务器打开一个ServerSocket,所有玩家都有自己的客户端,该客户端

简介

我的代码可以处理发送到服务器的所有字节,并决定是否让它们通过并最终发送响应。我想使用它将服务器作为web服务器、web套接字服务器和tcp服务器结合使用

虽然我的代码是为Minecraft编写的,但我并不是在Minecraft论坛上问这个问题,因为回答这个问题并不需要事先了解Minecraft或其代码库

有关Minecraft的所有您需要了解的信息

Minecraft是一款可以在线玩的Java游戏。在线播放时,有一台服务器打开一个ServerSocket,所有玩家都有自己的客户端,该客户端打开一个与服务器的ServerSocket通信的套接字

任何人都可以创建Minecraft服务器并在其服务器上安装服务器端修改(对于了解Minecraft的人来说,这些通常称为插件)。我的应用程序就是这样一个服务器端修改。大多数Minecraft服务器由Minecraft主机公司托管。服务器的所有者可以访问主机上管理服务器文件的部分

目标

我修改的目标是让Minecraft服务器服务于比Minecraft客户端更多的客户端。我希望同一台服务器也可以用作web服务器(用于http和https请求)以及(安全的)web套接字服务器和tcp服务器

为什么没有多个服务器套接字

最常见的解决方案是只为其他服务器类型创建一个ServerSocket,并为它们分配一个不同的端口。然而,这不是我的选择。大多数主机禁止您打开其他端口或要求额外的钱。所以我需要用Minecraft服务器插座来完成这一切

我迄今为止所取得的成就

到目前为止,我已经设法让发送到minecraft服务器的所有字节首先通过我的代码。我的代码可以选择是否让字节继续存在于Minecraft服务器代码中。它还可以自己发送响应,而无需通知Minecraft服务器代码

原则上,我所做的足以实现我的目标,但我希望在如何继续方面得到一些帮助。我将在下面解释到目前为止我已经完成和尚未完成的工作

Minecraft客户端发送到服务器的第一个字节始终相同,即16。这很好,因为它使我能够轻松地将Minecraft客户端与web浏览器和tcp客户端区分开来

HTTP请求和websocket连接总是以相同的字节开始,即71。HTTPS和安全WebSocket始终以字节22开头。我刚才提到的TCP连接将由我自己的应用程序发送,因此我可以选择它们将发送的字节,我可以简单地对修改进行编程以响应这些字节

我设法通过http请求和websocket连接的连接属性来区分它们。Http请求总是发送“连接:保持活动”,而websocket连接总是发送“连接:升级”。(尽管有些浏览器使用大写的k、a和u,而其他浏览器则不使用。)

处理普通的http请求并不难。处理TCP连接也不难,因为我会控制一切。但我对其余的连接类型有问题:

我需要帮助的问题

web套接字协议相当大,我不希望仅用代码就完全处理它。(我以前尝试过这个,但我一直在使用很少使用的部分,因此没有测试)因此我想使用一些库,让我只担心有效负载,而不是整个协议。不幸的是,web套接字库通常希望创建ServerSocket,这在我的例子中是不可能的那么,有人对在这里做什么有建议吗?

我没有找到任何关于如何正确读取https请求的信息有人能告诉我在哪里可以找到此协议的详细信息或提供一个好的链接吗? 对于安全web套接字,在了解如何读取请求后,我将面临与“正常”web套接字连接相同的问题

代码

到目前为止,我的所有代码都可以在上找到。最有趣的部分可能是我的代码有机会在到达Minecraft代码之前处理所有字节的部分,该代码如下所示

简短问题

对于那些不完全理解我的问题(你可以将其视为两个密切相关的问题)的人:

-我应该如何读取https请求和安全的web套接字握手

-有人知道一个库可以处理不需要创建ServerSocket本身的web套接字输入吗

// This channel handler will be registered for every connection client that will
                    // inspect
                    // any message before it reaches the Minecraft code.
                    pipeline.addFirst("multipurpose_handler_inspector", new ChannelInboundHandlerAdapter() {

                        private boolean deactivated;

                        private ChannelListener listener;

                        @Override
                        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                        //super.channelRead will send the content to the minecraft code
                            try {
                                if (!deactivated) {
                                    ByteBuf message = (ByteBuf) msg;
                                    if (listener != null) {
                                        listener.read(ctx, message);
                                    } else {
                                        byte firstByte = message.getByte(0);

                                        // All Minecraft connections start with the byte 16
                                        if (firstByte == 16) {
                                            deactivated = true;
                                            super.channelRead(ctx, msg);
                                        }

                                        // All insecure web connections start with the byte 71
                                        else if (firstByte == 71) {
                                            byte[] data = new byte[message.readableBytes()];
                                            message.getBytes(0, data);
                                            WebHandler.Type type = WebHandler.determineConnectionType(data);
                                            if (type == WebHandler.Type.HTTP) {
                                                listener = new HTTPListener();
                                                listener.readInitial(ctx, message);
                                            } else if (type == WebHandler.Type.WEBSOCKET) {
                                                // TODO Find a nice way to handle web socket connections
                                                listener = new WebSocketListener();
                                                listener.readInitial(ctx, message);
                                            } else {
                                                deactivated = true;
                                                super.channelRead(ctx, msg);
                                            }
                                        }

                                        // All secure web connections start with the byte 22
                                        else if (firstByte == 22) {
                                            // TODO implement the secure web protocols and find a way to read this stuff
                                            // and find the difference
                                            System.out.println(
                                                    "We are dealing with a secure websocket or https connection");
                                            byte[] data = new byte[message.readableBytes()];
                                            message.getBytes(0, data);
                                            System.out.println(new String(data));
                                        }

                                        // My applications
                                        else if (firstByte == 31) {
                                            listener = new TCPListener();
                                            listener.readInitial(ctx, message);
                                        } else {
                                            System.out.println("Unknown connection type");
                                            deactivated = true;
                                            super.channelRead(ctx, msg);
                                        }
                                    }
                                } else {
                                    super.channelRead(ctx, msg);
                                }
                            } catch (Exception ex) {
                                ex.printStackTrace();
                            }
                        }
                    });

如果您总是能够识别Minecraft流量,那么最好的选择可能是在同一个机器上运行apache/httpd和/或tomcat服务器,并将所有非Minecraft流量转发给它。如果您这样做,HTTPS内容可能只是正确配置HTTPS通信的http服务器的问题

您可能需要将代码配置为http代理——事实上(刚刚想到这一点),您可能想出去寻找一个开源http代理,然后用您的代码对其进行调整,以提取Minecraft流量并转发它,然后再做其他代理工作

我不会从头开始做HTTPs的事情,这不是非常困难,但我认为这很重要


哦,如果你的问题是“将Minecraft HTTPS流量与同一端口上的其他HTTPS连接区分开来”,那么我只能说这可能是你问题的一个很好的主题:)

我可以建议将你的问题总结为标题吗?你的头衔不是一个问题,而是一个问题