【问题标题】:How to handle HTTP request using Java Socket?如何使用 Java Socket 处理 HTTP 请求?
【发布时间】:2022-11-20 23:40:14
【问题描述】:

我正在尝试使用 Java 套接字和执行程序服务实现示例 HTTP 服务器以实现并发。但是,当我使用带有 2 个或更多请求或浏览器的 JMeter 运行测试时,每个第 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();
    }
}

【问题讨论】:

    标签: java multithreading serversocket java-threads java-server


    【解决方案1】:

    我不知道从哪里开始。您是否决定自己编写一半代码,让 stackoverflow 为您编写另一半?如果是这样的话,我会让你失望的,因为我只会告诉你缺少了什么,而不是如何填补。

    所以:

    我看到你打印 "Waiting for client..." 但我没有看到任何实际等待的代码。

    我看到你打印了"Getting empty request",但我没有看到任何收到任何请求的代码。

    您的服务器启动,并等待连接。客户端建立连接,但在客户端有机会发送请求之前,服务器发送响应并终止。因此,连接在客户端有机会发送其请求之前关闭。

    如果它只有一半的时间有效,那么令我困惑的是它实际上有一半的时间有效。 (好吧,在你看来它有效。)

    【讨论】:

      【解决方案2】:

      问题是 lamba 引用了一个唯一的变量服务器。第二个连接覆盖变量。 尝试类似的东西

      public class Service {
          public static void main(String[] args) throws Exception {
              ServerSocket serverSocket = new ServerSocket(8080);
              var executors = Executors.newFixedThreadPool(4);
              while(true) {
                  try {
                      Socket server = serverSocket.accept();
      
                      executors.submit(new ConnectionService(serverSocket, server));
                  } catch (Exception e) {
                      e.printStackTrace();
                      break;
                  }
              }
      
              serverSocket.close();
          }
          
          
          static class ConnectionService implements Runnable {
      
              Socket socket;
              ServerSocket serverSocket;
              
              ConnectionService(ServerSocket serverSocket,Socket server) {
                  this.serverSocket = serverSocket;
                  this.socket = server;
              }
      
      
              @Override
              public void run() {
                  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
      " +
                                  "Content-Type: text/plain
      " +
                                  "Content-Length: " + text.length() + "
      
      "
                                  + text;
                      socket.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");
                          socket.close();
                      } catch (Exception e) {
                          System.out.println("Executor error2: ");
                          e.printStackTrace();
                      }
                  }
              }
              
          }
      }
      

      【讨论】:

      • 感谢您的回答@andrea。但我认为变量不是问题,因为根据 Java 的性质,我传递的是对值的引用,对吧?但是为了以防万一,我也尝试了您的版本,但是仍然每秒钟请求都会失败。这是用 500 rps 测试请求的 JMeter 场景:pastebin.com/x1Xk78Hp
      • @Sabyrzhan 我发布的代码工作正常。我确认您的代码的问题是服务器变量。服务器变量未传递给 lamba,但每个 lamba 引用相同的服务器变量
      • 但是你试过在链接中运行JMeter场景吗?您确定没有任何请求失败吗?
      • 我使用多个并发请求运行测试,但我不使用 JMeter。
      • @anrea 你能用 JMeter 试试吗?然后你会看到它在实际负载上失败了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-28
      • 2011-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多