简体   繁体   中英

How do I force a Java Socket's InputStream to throw an IOException?

I'm testing a networking component I've built on top of java.net.Socket . I have code like this:

try {
   byte[] buffer = new byte[1024]
   int bytesRead = socket.getInputStream().read(buffer);
   // more processing
} catch (IOException e) {
   handleException(e);
}

How can I force my InputStream#read call to throw an IOException so I can test the handleException method? I don't want to use mocking. I want to use the real implementation, and I want to use only Java APIs.

TLDR

From the writing side, use an abortive close:

socket.setSoLinger(true, 0);
socket.close();

This will cause any subsequent reads from the other side to throw an IOException

More detail from Oracle's documentation :

First, we need to distinguish the differences between an abortive and an orderly connection release. To understand this distinction we need to look at what happens at the TCP protocol level. It is helpful to imagine an established TCP connection as actually two separate, semi-independent streams of data. If the two peers are A and B, then one stream delivers data from A to B, and the other stream from B to A. An orderly release occurs in two stages. First one side (say A) decides to stop sending data and sends a FIN message across to B. When the TCP stack at B's side receives the FIN it knows that no more data is coming from A, and whenever B reads all preceding data off the socket, further reads will return the value -1 to indicate end-of-file. This procedure is known as the TCP half-close, because only one half of the connection is closed. Not surprisingly, the procedure for the other half is exactly the same. B sends a FIN message to A, who eventually receives a -1 after reading all preceding data sent by A off the socket.

By contrast, an abortive close uses the RST (Reset) message. If either side issues an RST, this means the entire connection is aborted and the TCP stack can throw away any queued data which has not been sent or received by either application.

So, how do Java applications perform orderly and abortive releases? Let's consider abortive releases first. A convention that has existed since the days of the original BSD sockets is that the "linger" socket option can be used to force an abortive connection release. Either application can call Socket.setLinger (true, 0) to tell the TCP stack that when this socket is closed, the abortive (RST) procedure is to be used. Setting the linger option has no immediate effect, except that when Socket.close() is called subsequently, the connection is aborted with an RST message. As we will see shortly, there are other ways that may cause a connection to be aborted, but this is the simplest way to make it happen.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM