gpt4 book ai didi

java - 当我从客户端关闭套接字时,socket.getInputStream.read() 不会抛出异常

转载 作者:行者123 更新时间:2023-12-01 15:39:20 26 4
gpt4 key购买 nike

我使用的是 Windows 7 x64。我正在编写一个服务器,它为每个传入连接打开一个线程 - 该线程从连接的输入流中读取。如果套接字被关闭(),read()应该阻塞并抛出异常。它不 - 只是返回 -1。如果我不关闭来自客户端的连接 - 只需让客户端终止 - 我会按预期重置连接 - 但如果我 close() 来自客户端的连接(或只是客户端的输出流) read()在服务器线程中不会抛出异常 - 只是返回-1docs对此非常清楚:

public void close() throws IOException

Closes this socket.

Any thread currently blocked in an I/O operation upon this socket will throw a SocketException.

帮助

工作代码:

服务器:

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class CloseTest {
private int port;

public CloseTest(int port) {
this.port = port;
}

void base_station_activate() {
ServerSocket baseStationListeningSocket=null;
try {
baseStationListeningSocket = new ServerSocket(this.port, 1, InetAddress.getByName("127.0.0.1"));
} catch (IOException ex) {
}

main_server: while (true) {
try {
Socket clientSocket = baseStationListeningSocket.accept();
BaseStationClientHandler ch = new BaseStationClientHandler(clientSocket);
Thread myThread = new Thread(ch);
myThread.start();
} catch (IOException ex) {
System.exit(1);
} // main_server
finally {
// baseStationListeningSocket.close()
}
}
}
public static void main(String args[]){
CloseTest bs = new CloseTest(8082);
bs.base_station_activate();
}
public class BaseStationClientHandler implements Runnable {
private final Socket clientSocket;

private BaseStationClientHandler(Socket clientSocket) {
this.clientSocket = clientSocket;
}

public void run() {
String debug_message = null;
try {
InputStream in = clientSocket.getInputStream();
// read message and respond
String s = "";
char x;
int r;
server: while (true) {
try {
while ((r = in.read()) != (int) '%') {
if (r == -1) {
debug_message = "Stream/socket .closed() - exception not thrown (WHYYYYY ????) by client";
System.out.println(debug_message);
break server;
}
x = (char) r;
s += x;
}
System.out.println(s);
} catch (SocketException socketException) {
System.out.println(socketException.getLocalizedMessage()); // if connection reset (but not if Stream/socket .closed()) read throws !!!!!
debug_message = "socket_reset";
break server;
}
s = "";
} //server
} catch (IOException ex) {
System.out.println("IOexception in client handler - check if thrown by read");
} finally {
try {
clientSocket.close();
} catch (IOException ex) {
}
}
}
}
}

客户:

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Vector;

public class CloseTestClient {

public CloseTestClient(int port, String ipAddress){
Vector<Socket> connections = new Vector<Socket>();
try {
for(int i=0;i<20;i++){
Socket connection = new Socket(InetAddress.getByName(ipAddress), port);
connections.add(connection);
OutputStream out = connection.getOutputStream();
out.write( ("CONNECT#"+(i+1)+"#1%").getBytes());
System.out.println("[CloseTestClient SENT]:"+"CONNECT#"+(i+1)+"#1%");
Thread.sleep(1000); // to be sure the server threads are blocked in the read()
// connection.close(); // if I comment this out I see the connection reset message from the server when this main terminates
// commented it out finally and moved the closing at the end to be sure the server threads are blocked in read()
}
} catch (Exception ex) {
ex.printStackTrace();
}
finally{
// if I comment *for* out I see the "connection_reset" message from the server when this main terminates
for (Socket c : connections){
try{
c.close();
}catch(Exception ex){
}
}
}
}

public static void main(String args[]){
System.out.println("CloseTestClient run !");
new CloseTestClient(8082,"127.0.0.1");
}
}

最佳答案

您所指的文档适用于该计算机上的线程,而不是远程线程。如果线程 A 在套接字 X 上进行 read(),并且同一进程的线程 B 关闭了套接字 X,则线程 A 的读取调用将引发异常。

当本地计算机上的套接字被 close() 时,远程计算机可以确定不再有数据通过套接字传入,因此它返回 -1(请参阅 InputStream 的 read() 文档)。这就是当您显式关闭客户端上的连接时发生的情况。服务器知道不会有更多数据到来,因此 read() 很乐意返回 -1。没有特殊情况。

我猜测,当您让客户端终止而不在套接字上调用 close() 时,JVM 或操作系统将发送 TCP RST,而不是很好地关闭连接(发送 TCP FIN)。这会导致服务器上的 read() 调用抛出异常。

关于java - 当我从客户端关闭套接字时,socket.getInputStream.read() 不会抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8334045/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com