繁体   English   中英

如何使用 Java Socket 处理 HTTP 请求?

[英]How to handle HTTP request using Java Socket?

我正在尝试使用 Java 套接字和并发执行程序服务来实现示例 HTTP 服务器。 但是,当我使用 JMeter 和 2 个或更多请求或浏览器运行测试时,每个第 2 个请求都会失败。

如何正确处理请求? 这是示例源代码:

public class Service {
    public static void main(String[] args) throws Exception {
        var serverSocket = new ServerSocket(8080);
        var executors = Executors.newFixedThreadPool(4);
        while(true) {
            try {
                var server = serverSocket.accept();

                executors.submit(() -> {
                    try {
                        var text = "sample";
                        System.out.println("Waiting for client on port " +
                                serverSocket.getLocalPort() + "...");

                        System.out.println("Getting empty request");
                        var response = "HTTP/1.1 200 OK\r\n" +
                                    "Content-Type: text/plain\r\n" +
                                    "Content-Length: " + text.length() + "\r\n\r\n"
                                    + text;
                        server.getOutputStream().write(response.getBytes(StandardCharsets.UTF_8));
                    } catch (Exception e) {
                        System.out.println("Executor error:" + e.toString());
                        e.printStackTrace();
                    } finally {
                        try {
                            System.out.println("Closing server");
                            server.close();
                        } catch (Exception e) {
                            System.out.println("Executor error2: ");
                            e.printStackTrace();
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
        }

        serverSocket.close();
    }
}

你的第一个问题在于你的回应。

"HTTP/1.1 200 OK\r\n"

这允许您不处理的保持活动状态。 一个基本的 JMeter 采样器尝试使用 keep alive,这就是为什么你总是在第二次尝试时失败。

你可以把它改成

"HTTP/1.0 200 OK\r\n"

那不支持保持活动状态,因此您将使用当前代码获得更多成功。 对我来说,在 JMeter 出现另一个错误之前,我只收到了 1000 条回复,但我不知道错误是什么。

为了支持 keep alive,需要解析请求。 这是一个例子。

    int clients = 0;
    while(true) {
        try {
            System.out.println("Waiting for client on port " +
                            serverSocket.getLocalPort() + "...");
            var server = serverSocket.accept();
            final int client_no = clients++;
            System.out.println("handling: " + client_no);
            executors.submit(() -> {
                int sent = 0;
                try {
                    var is = server.getInputStream();
                    var os = server.getOutputStream();
                    
                    var text = "sample";
                    byte[] tb = text.getBytes(StandardCharsets.UTF_8);

                    char[] buffer = new char[256];
                    int cr_count = 0;
                    while( true ){
                        
                        int i=0;
                        int r = is.read();
                        if(r == -1) break;
                        
                        while( r != -1 ){
                            char c = (char)r;
                            if( c == '\n' ){
                                cr_count++;
                            } else if( c != '\r' ){
                                cr_count = 0;
                            }
                            buffer[i++] = c;
                            if(cr_count == 2) break;
                            r = is.read();
                        }
                        //System.out.println("request: " + new String(buffer));
                        var response = "HTTP/1.1 200 OK\r\n" +
                                    "Content-Type: text/plain\r\n" +
                                    "Content-Length: " + tb.length + "\r\n\r\n";
                        os.write(response.getBytes(StandardCharsets.UTF_8));
                        os.write(tb);
                        os.flush();
                        sent++;
                    }
                } catch (Exception e) {
                    System.out.println("Executor error:" + e.toString());
                    e.printStackTrace();
                } finally {
                    try {
                        System.out.println("Closing connection!");
                        server.close();
                    } catch (Exception e) {
                        System.out.println("Executor error2: ");
                        e.printStackTrace();
                    }
                    System.out.println("sent " + sent + " responses to client " + client_no);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            break;
        }
    }

这将为我运行 JMeter 测试。 它可以使用 1.0 或 1.1 并完成数千个请求中的 10 个。 如果我使用 keep alive (1.1) 每个客户端处理许多请求,如果我不使用 keep alive (1.0) 每个客户端处理 1 个请求。

如果我不读取请求 header,那么 http 1.0 版本将在几千个请求后停止。

这也是与您原来的“在第二次请求后死亡”不同的问题。 这是因为您实际上并没有使用 HTTP 1.1 !

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM