Java Socket TCP 套接字超時


套接字超時

設置超時

API:java.net.Socket 1.0

  • void setSoTimeout(int timeout) 1.1
    設置該套接字上讀請求的阻塞時間。如果超過了給定時間,則拋出一個 InterruptedIOException 異常。

setSoTimeout 的底層代碼:

getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));

服務器超時

ServerSocket#accept 等待連接超時

public class TimeoutSocketServer {

    public static void main(String[] args) {
        long startTime = 0L;
        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            serverSocket.setSoTimeout(1000);

            while (true) {
                startTime = System.currentTimeMillis();
                serverSocket.accept();
            }
        } catch (IOException e) {
            long timeout = System.currentTimeMillis() - startTime;
            System.out.println(timeout);
            e.printStackTrace();
        }
    }
}

控制台輸出:
server-accept-timeout

read 讀超時

public class TimeoutSocketServer {

    public static void main(String[] args) throws IOException {
        long readTime = 0L;
        ServerSocket serverSocket = new ServerSocket(8080);

        while (true) {
            Socket socket = serverSocket.accept();
            socket.setSoTimeout(1000);
            if (socket != null) {
                System.out.println("客戶端連接上了");
                try {
                    InputStream inStream = socket.getInputStream();
                    byte[] bytes = new byte[1024];
                    readTime = System.currentTimeMillis();
                    while (inStream.read(bytes) != 0) {
                        System.out.println(Arrays.toString(bytes));
                    }
                } catch (IOException e) {
                    long timeout = System.currentTimeMillis() - readTime;
                    System.out.println(timeout);
                    e.printStackTrace();
                }
            }
        }
    }
}

輸入命令 telnet 127.0.0.1 8080 啟動客戶端連接,但是不發送內容。

控制台輸出:
Read-Timed-Out

客戶端超時

Socket#connect連接超時

通過先構建一個無連接的套接字,然后再使用一個超時來進行連接的方法。

public class TimeoutClient {

    public static void main(String[] args)  {
        Socket socket = new Socket();
        long startTime = System.currentTimeMillis();
        try {
            socket.connect(new InetSocketAddress("127.0.0.1", 8080), 1000);
        } catch (IOException e) {
            long timeout = System.currentTimeMillis() - startTime;
            System.out.println(timeout);
            e.printStackTrace();
        }
    }
}

控制台輸出:
connect-timed-out
當然,我在這個實驗中,沒有啟動服務端,如果客戶端不設置 timeout 超時參數的話,連接代碼改為下面這段:

socket.connect(new InetSocketAddress("127.0.0.1", 8080));

此時的控制台輸出為服務端拒絕連接:
Refused

讀超時

服務端代碼

public class Server {

    public static void main(String[] args) throws IOException {
        long readTime = 0L;
        ServerSocket serverSocket = new ServerSocket(8080);
        Socket socket = serverSocket.accept();
        System.out.println("客戶端連接上了");
        System.in.read();
    }
}

客戶端代碼

public class TimeoutClient {

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket();
        socket.setSoTimeout(3000);
        socket.connect(new InetSocketAddress("127.0.0.1", 8080));
        long startTime = 0;
        try {
            InputStream inStream = socket.getInputStream();
            startTime = System.currentTimeMillis();
            while (inStream.read() != 0) {
                System.out.println("接收到了信息");
            }
        } catch (IOException e) {
            long timeout = System.currentTimeMillis() - startTime;
            System.out.println(timeout);
            e.printStackTrace();
        }
    }
}

先啟動服務端,再啟動客戶端,控制台輸出結果如下:
client-read-timeout

總結

Socket#setSoTimeout 可以設置讀超時時長。如果超過了給定時間,則拋出一個 InterruptedIOException 異常。
ServerSocket#setTimeout 可以設置 ServerSocket#accept 的等待連接的超時時間,如果超過了給定時間,則拋出一個 InterruptedIOException 異常。
Socket#connect 有一個 timeout 參數,可以設置連接超時時長。
InterruptedIOException 時 SocketTimeoutException 的父類。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM