繁体   English   中英

多线程Java代理服务器

[英]Multithreaded Java proxy server

我对Stack Overflow有点陌生,所以如果我做错了什么,请随时告诉我。 我还没有找到其他帖子以对我有意义的方式解决这个问题。

因此,我的最终目标是用Java编写多线程HTTP代理服务器,但是第一步,我只是尝试将通过浏览器建立的连接的输入流写入窗口。

这是我的代码:

private static ServerSocket welcomeSocket;
private static Socket connectionSocket;

private static Socket clientSocket;

private static OutputStream clientOutput;
private static InputStream proxyInput;

private static BufferedReader reader;

private static InetSocketAddress clientStream;

public static void main(String[] args) throws IOException, URISyntaxException {

    // Create socket, port 12345, for incoming request
    welcomeSocket = new ServerSocket(12345);
    while(true){
        try(Socket clientSocket = welcomeSocket.accept()){
        BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));

        Thread t = new Thread(){  
            public void run(){
                System.out.println("running\n");
                try{
                    System.out.println("trying\n");
                    String lineIn;
                    while((lineIn = reader.readLine()) != null){
                        System.out.println("writing\n");
                        writer.write(lineIn);
                        writer.newLine();
                    }
                }
                catch(IOException i){
                    try {                            
                        Logger.getLogger(EECS325_Project1.class.getName()).log(Level.SEVERE, null, i);
                        throw i;
                    } catch (IOException ex) {
                        Logger.getLogger(EECS325_Project1.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        };
        t.start();
        }
    }

}

但是,当我在浏览器中转到localhost:12345时,出现以下异常:

     Nov 04, 2015 9:53:44 AM eecs325_project1.EECS325_Project1$1 run
     SEVERE: null
     java.net.SocketException: socket closed
     at java.net.SocketInputStream.socketRead0(Native Method)
     at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
     at java.net.SocketInputStream.read(SocketInputStream.java:170)
     at java.net.SocketInputStream.read(SocketInputStream.java:141)
     at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
     at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
     at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
     at java.io.InputStreamReader.read(InputStreamReader.java:184)
     at java.io.BufferedReader.fill(BufferedReader.java:161)
     at java.io.BufferedReader.readLine(BufferedReader.java:324)
     at java.io.BufferedReader.readLine(BufferedReader.java:389)
     at eecs325_project1.EECS325_Project1$1.run(EECS325_Project1.java:46)

大多数帖子都说这种异常是在关闭读写器并有效地关闭套接字时发生的。 但是,绝对不要关闭读取器,写入器或套接字。

任何帮助将不胜感激!

您的try-with-resources块在Thread执行之前关闭了客户端套接字-这意味着当Thread尝试使用它们时, readerwriter reader引用了封闭的基础流。

将try-with-resources块移到线程内部的解决方案:

final Socket clientSocket = welcomeSocket.accept();
Thread t = new Thread(){  
  @Override public void run(){
    // BufferedReader/Writer close the underlying stream when they
    // are closed, so the socket will be closed when this
    // try-with-resources block finishes.
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())));
         BufferedWriter writer = ...) {
      // Do whatever.
    } catch (IOException e) {
      // Handle the exception.
    }
  }
};
t.start();

这意味着直到线程运行,特别是在您完成与readerwriter之后,关闭才会发生。

注意:您必须注意确保始终关闭Socket:如果在创建线程或创建BufferedReader时发生异常,则不会发生这种情况。 这些情况有些古怪,涉及一些额外的try / catch / finally块; 我宁愿不将这些添加到答案中,因为我认为它们只是使主要思想难以理解。

rivate static ServerSocket welcomeSocket;
private static Socket connectionSocket;

private static Socket clientSocket;

private static OutputStream clientOutput;
private static InputStream proxyInput;

private static BufferedReader reader;

private static InetSocketAddress clientStream;

这些数据项中的任何一项都不应该是静态的,与特定客户端有关的数据项(接受的套接字,其上游套接字及其流)应该在单独的Runnable连接处理程序类中,该类在每个接受的套接字和一个Thread实例化。创建运行它。

暂无
暂无

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

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