如何重现"java.net.SocketException.Connection reset"?
How to reproduce "java.net.SocketException.Connection reset"?
我正在尝试重现 "java.net.SocketException.Connection reset" 异常。
想知道是否有可用的程序可以帮助我模拟它。我尝试按照服务器和客户端程序来查看是否可以模拟,但我无法获得任何异常。我正在使用 java8.
服务器代码-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
public class SimpleServerApp {
public static void main(String[] args) throws InterruptedException {
new Thread(new SimpleServer()).start();
}
static class SimpleServer implements Runnable {
@Override
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(3333);
serverSocket.setSoTimeout(0);
//serverSocket.
while (true) {
try {
Socket clientSocket = serverSocket.accept();
BufferedReader inputReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("Client said :"+ inputReader.readLine());
} catch (SocketTimeoutException e) {
e.printStackTrace();
}
}
}catch (Exception e) {
e.printStackTrace();
System.out.println(" EXCEPTION " + e.getStackTrace());
}/*catch (IOException e1) {
e1.printStackTrace();
}*/ /*finally {
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}*/
}
}
}
客户代码 -
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
public class SimpleClientApp {
public static void main(String[] args) {
new Thread(new SimpleClient()).start();
}
static class SimpleClient implements Runnable {
@Override
public void run() {
Socket socket = null;
try {
socket = new Socket("localhost", 3333);
PrintWriter outWriter = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Wait");
Thread.sleep(20000);
//System.exit(0);
//throw new Exception("Random exception");
//socket.close();
outWriter.println("Hello Mr. Server!");
}catch (SocketException e) {
e.printStackTrace();
}catch (InterruptedException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} /*finally {
try {
if (socket != null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
*/ }
}
}
场景一。
- 在本地启动服务器程序。
- 在本地启动客户端程序。
- 突然关闭客户端程序 (Ctrl C) - 我刚刚得到输出
服务器程序 "Client said :null"
场景 2.
- 在本地启动服务器程序。
- 在本地启动客户端程序。
- 客户端已连接到服务器,然后在客户端程序等待期间突然关闭服务器程序。仍然没有例外。
有人能告诉我一些可以产生连接重置异常的方法吗?使用示例代码。
这对我有用:
class Server {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(9999);
Socket s = ss.accept();
InputStream i = s.getInputStream();
i.read();
}
}
客户端在不关闭套接字的情况下连接和断开连接
class Client {
public static void main(String[] args) throws Exception {
Socket s = new Socket("localhost", 9999);
}
}
这导致服务器出现异常
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at net.Server.main(Server.java:13)
有几种方法。我不会 post 其中之一,因为它被滥用太多了,但制作它的简单方法是:
- 获取套接字后立即关闭套接字,不读取任何内容。如果发件人是向您发送邮件而不是从您那里读取信息,则此方法有效。
- 如果您知道发件人已发送某些内容,请关闭套接字而不以任何方式读取它。
None 以上答案在 Mac 和 Linux 上对我都有效。
经过大量谷歌搜索后,我以 article 解释了如何做结束。明确一点:我试图从客户端重现连接重置,即 "Connection reset by peer"。
我尝试启动一个 运行 netcat 进程,然后突然终止该进程 - 仅在 Mac 上有效。
我从另一个线程尝试 socket.close,同一个线程 - 没有任何效果。
简单地说,所有这些方法都没有导致客户端向服务器发送RST,从而导致异常(由对等方重置)。
以下有效:
- 设置任何服务器 - 在我的例子中是 Netty(他们的入门 Discard 服务器就可以)。
- 使用以下客户端代码:
final Socket socket = new Socket("localhost", port);;
socket.setSoLinger(true, 0);
final OutputStream outputStream = socket.getOutputStream();
for (int i=0; i <= 500; i++) {
outputStream.write('a');
}
outputStream.write('\n');
outputStream.flush();
socket.close();
Thread.sleep(2000);
soLinger() 是魔术。根据上面引用的 Oracle 文章,当您调用 socket.close() 时,它会向另一方发送 RST,而不是发送 FIN,然后等待另一方完成读取 FIN 之前发送的内容 - 即强制关闭。
我花了 1 天的时间才找到这个,所以我希望它能节省你的工作时间。
与其使用 Java 客户端代码引发此异常,我发现编写一个简短的 Python 脚本更容易:
import struct, socket
s = socket.socket(socket.AF_INET6)
s.connect(("::1", 8000))
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
s.close() # provokes Connection Reset at host
我正在尝试重现 "java.net.SocketException.Connection reset" 异常。
想知道是否有可用的程序可以帮助我模拟它。我尝试按照服务器和客户端程序来查看是否可以模拟,但我无法获得任何异常。我正在使用 java8.
服务器代码-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
public class SimpleServerApp {
public static void main(String[] args) throws InterruptedException {
new Thread(new SimpleServer()).start();
}
static class SimpleServer implements Runnable {
@Override
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(3333);
serverSocket.setSoTimeout(0);
//serverSocket.
while (true) {
try {
Socket clientSocket = serverSocket.accept();
BufferedReader inputReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("Client said :"+ inputReader.readLine());
} catch (SocketTimeoutException e) {
e.printStackTrace();
}
}
}catch (Exception e) {
e.printStackTrace();
System.out.println(" EXCEPTION " + e.getStackTrace());
}/*catch (IOException e1) {
e1.printStackTrace();
}*/ /*finally {
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}*/
}
}
}
客户代码 -
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
public class SimpleClientApp {
public static void main(String[] args) {
new Thread(new SimpleClient()).start();
}
static class SimpleClient implements Runnable {
@Override
public void run() {
Socket socket = null;
try {
socket = new Socket("localhost", 3333);
PrintWriter outWriter = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Wait");
Thread.sleep(20000);
//System.exit(0);
//throw new Exception("Random exception");
//socket.close();
outWriter.println("Hello Mr. Server!");
}catch (SocketException e) {
e.printStackTrace();
}catch (InterruptedException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} /*finally {
try {
if (socket != null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
*/ }
}
}
场景一。
- 在本地启动服务器程序。
- 在本地启动客户端程序。
- 突然关闭客户端程序 (Ctrl C) - 我刚刚得到输出 服务器程序 "Client said :null"
场景 2.
- 在本地启动服务器程序。
- 在本地启动客户端程序。
- 客户端已连接到服务器,然后在客户端程序等待期间突然关闭服务器程序。仍然没有例外。
有人能告诉我一些可以产生连接重置异常的方法吗?使用示例代码。
这对我有用:
class Server {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(9999);
Socket s = ss.accept();
InputStream i = s.getInputStream();
i.read();
}
}
客户端在不关闭套接字的情况下连接和断开连接
class Client {
public static void main(String[] args) throws Exception {
Socket s = new Socket("localhost", 9999);
}
}
这导致服务器出现异常
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at net.Server.main(Server.java:13)
有几种方法。我不会 post 其中之一,因为它被滥用太多了,但制作它的简单方法是:
- 获取套接字后立即关闭套接字,不读取任何内容。如果发件人是向您发送邮件而不是从您那里读取信息,则此方法有效。
- 如果您知道发件人已发送某些内容,请关闭套接字而不以任何方式读取它。
None 以上答案在 Mac 和 Linux 上对我都有效。 经过大量谷歌搜索后,我以 article 解释了如何做结束。明确一点:我试图从客户端重现连接重置,即 "Connection reset by peer"。
我尝试启动一个 运行 netcat 进程,然后突然终止该进程 - 仅在 Mac 上有效。
我从另一个线程尝试 socket.close,同一个线程 - 没有任何效果。
简单地说,所有这些方法都没有导致客户端向服务器发送RST,从而导致异常(由对等方重置)。
以下有效:
- 设置任何服务器 - 在我的例子中是 Netty(他们的入门 Discard 服务器就可以)。
- 使用以下客户端代码:
final Socket socket = new Socket("localhost", port);;
socket.setSoLinger(true, 0);
final OutputStream outputStream = socket.getOutputStream();
for (int i=0; i <= 500; i++) {
outputStream.write('a');
}
outputStream.write('\n');
outputStream.flush();
socket.close();
Thread.sleep(2000);
soLinger() 是魔术。根据上面引用的 Oracle 文章,当您调用 socket.close() 时,它会向另一方发送 RST,而不是发送 FIN,然后等待另一方完成读取 FIN 之前发送的内容 - 即强制关闭。
我花了 1 天的时间才找到这个,所以我希望它能节省你的工作时间。
与其使用 Java 客户端代码引发此异常,我发现编写一个简短的 Python 脚本更容易:
import struct, socket
s = socket.socket(socket.AF_INET6)
s.connect(("::1", 8000))
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
s.close() # provokes Connection Reset at host