pit*_*ker 1 java sockets multithreading try-with-resources
我想编写一个简单的服务器来侦听端口并生成新线程来处理新连接.我试图使用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();
}
}
Run Code Online (Sandbox Code Playgroud)
b)完全相同,但尝试使用资源(不起作用):
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();
}
}
Run Code Online (Sandbox Code Playgroud)
a)中的示例与预期的一样.b)中的示例接受连接但立即关闭.有人可以向我解释原因并告诉我我是如何正确地做到这一点的吗?
结构
try (resource = ...) {
}
Run Code Online (Sandbox Code Playgroud)
相当于
resource = null;
try {
resource = ...;
} finally {
if (resource != null) {
resource.close();
}
}
Run Code Online (Sandbox Code Playgroud)
而已.它只是一种语法糖,只是写出相同的更短的方式.因此,当您将语句Socket clientSocket = serverSocket.accept();放入try-with-resource块时,实际上一旦离开块就关闭它.
当流的处理同步完成时,即当您打开流,读取或写入并关闭它时,此结构很好.
在您的情况下,您获取流并在单独的线程中处理它,因此无法立即关闭它.客户端应决定关闭流本身.例如,当用户按下"断开连接"按钮或服务器发送特殊应用程序级别命令"关闭连接"或IOException抛出时.
| 归档时间: |
|
| 查看次数: |
2890 次 |
| 最近记录: |