【发布时间】:2014-12-01 15:02:13
【问题描述】:
我想编写一个简单的服务器来侦听端口并生成新线程来处理新连接。 我尝试使用try-with-resources 接受新连接但失败了,因为子线程中的套接字似乎立即关闭,我不明白为什么。
这里有 2 个简化的示例。
a) 服务器的工作示例(没有 try-with-resources):
package MyTest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServerA implements Runnable {
private int port;
private ServerSocket serverSocket;
public MyServerA(Integer port) {
this.port = port;
}
@Override
public void run() {
try {
serverSocket = new ServerSocket(port);
} catch(IOException ioe) {
System.err.println("error opening socket. " + ioe.getStackTrace());
}
while (true) {
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
cliThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientServiceThread extends Thread {
private Socket s;
boolean goOn = true;
ClientServiceThread(Socket s) {
this.s = s;
}
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.s.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(this.s.getOutputStream()));
while (goOn) {
final String req = in.readLine();
if (req != null) {
System.out.println("got: " + req);
out.println("you said: " + req);
out.flush();
if (req.contains("bye")) {
System.out.println("closing thread");
goOn = false;
}
}
}
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyServerA a = new MyServerA(30000);
a.run();
}
}
b) 完全相同,但使用 try-with-resources(不起作用):
package MyTest;
import java.io.BufferedReader;
public class MyServerB implements Runnable {
private int port;
private ServerSocket serverSocket;
public MyServerB(Integer port) {
this.port = port;
}
@Override
public void run() {
try {
serverSocket = new ServerSocket(port);
} catch(IOException ioe) {
System.err.println("error opening socket. " + ioe.getStackTrace());
}
while (true) {
try (Socket clientSocket = serverSocket.accept();) {
ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
cliThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientServiceThread extends Thread {
private Socket s;
boolean goOn = true;
ClientServiceThread(Socket s) {
this.s = s;
}
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.s.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(this.s.getOutputStream()));
while (goOn) {
final String req = in.readLine();
if (req != null) {
System.out.println("got: " + req);
out.println("you said: " + req);
out.flush();
if (req.contains("bye")) {
System.out.println("closing thread");
goOn = false;
}
}
}
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyServerB b = new MyServerB(30000);
b.run();
}
}
a) 中的示例按预期工作。 b) 中的示例接受连接但立即关闭它。 有人可以向我解释原因并告诉我如何正确执行此操作吗?
【问题讨论】:
-
这是意料之中的,因为这是 try-with-resources 的工作方式……在 try 块之后,在开头括号中声明的所有资源都将关闭。
-
感谢您的回答。那么你会说在这里使用 try-with-resources 是错误的方法吗?你能推荐一个更优雅的版本吗?
-
好吧,只是传递套接字,并在线程中使用 try-with-resources 语句使其关闭(您可以
final Socket socket = s;s已经存在) -
另外,您应该考虑使用 ExecutorService 而不是原始线程
标签: java multithreading sockets try-with-resources