我对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)
大多数帖子都说当关闭读取器/写入器,有效关闭套接字时会发生此异常。但是,我决不会关闭阅读器,写入器或套接字。
非常感谢任何帮助!
答案 0 :(得分:1)
您的try-with-resources块在Thread执行之前关闭客户端套接字 - 这意味着当线程尝试使用它们时reader
和writer
引用已关闭的底层流。
解决方案将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();
这意味着在线程运行之前不会发生结束,更具体地说,在您完成reader
和writer
的操作之后。
注意:您必须注意确保Socket 始终关闭:如果在创建Thread或创建BufferedReader时出现异常,则不会发生这种情况。这些情况有点粗糙,并涉及一些额外的try / catch / finally块;我宁愿不将这些添加到答案中,因为我认为它们只是模糊了主要想法。
答案 1 :(得分:0)
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
来运行它。