程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Java SE ——TCP協議網絡編程(三),se網絡編程

Java SE ——TCP協議網絡編程(三),se網絡編程

編輯:JAVA綜合教程

Java SE ——TCP協議網絡編程(三),se網絡編程


之前的代碼中關閉了 socket 對象的輸入流與輸出流,但並沒有關閉掉socket 對象,會造成服務器資源的浪費,應通過調用 socket 的 close() 方法來關閉當前的socket 對象。

 

因此,可以通過創建一個  ServerScanThread 線程,使其一直在後台運行,掃描看哪些 socket 對象的 Input Stream 與 OutputStream 均已關閉,當掃描到當前 socket 對象的輸入輸出流均已關閉,則關閉當前 socket 對象。

掃描線程代碼:

public class ServerScanThread extends Thread {
    public static List<Socket> socketList = new LinkedList<Socket>(); //實例化一個靜態列表,使其存放 Socket,使用LinkedList 便於刪除
    public ServerScanThread(){
        setDaemon(true);//設置為後台線程
        start();
    }
    public void run(){
        while(true){
            //1.我要去掃描整個集合,如果當前集合是空的,我就去睡覺去喽
            while(socketList == null ||socketList.size()<= 0){
                System.out.println("這會兒集合裡沒有socket,我先睡覺10s");//測試代碼
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            }
            //2.如果運行到這裡,則說明 socketList 中有元素,則有開始掃描判斷其socket 對象是否已經關閉了其輸入流和輸入流。
            for(int i = 0;i<socketList.size();i++){
                Socket socket = socketList.get(i);//從socketList 集合中獲得一個 socket 對象。
                if(socket.isInputShutdown() & socket.isOutputShutdown()){
                    try {
                        socket.close();//關閉當前 socket 對象
                        socketList.remove(i);//從當前列表中移除當前 socket 對象。
                        System.out.println("有一個 socket 被關閉了");//測試代碼
                        //i--; LinkedList在移除掉一個元素後,其後邊的元素下標統統會減一,為保證不會跳過某一個元素,可在此處將 i 自減,也可以不因為會進行再次掃描
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            try {

Thread.sleep(5000);//掃描完一遍之後休息五秒鐘 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }//整個線程完成後可以在 Server 中進行調用。 } }

服務器端代碼:

public class Server1 {

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        try {
            
            @SuppressWarnings("resource")
            ServerSocket server = new ServerSocket(9880);
            new ServerScanThread();
            while (true){
                 Socket client = server.accept();
                 ServerScanThread.socketList.add(client);//在 socketList 集合中加入 socket 實例對象
                 System.out.println("來自"+ client.getInetAddress().getHostAddress()+"的客戶端已連接成功!");
                 if(client != null){
                     //開始對話
                    
                     new WriterThread("服務端",client);
                     new ReaderThread("服務端",client);
                        
                         
                 }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        
        input.close();

    }

}
  • 當沒有客戶端運行時的輸出:

此時沒有socket對象,程序不停在內部的第一個while 循環裡運行,每隔十秒打印一次。

  • 當運行客戶端但不關閉socket 的輸入輸出流時的輸出:

由於是先運行的服務器端,所以while 循環先會執行一次,這次循環中還沒有socket 對象,當客戶端開始運行時,由於沒有輸入 byebye ,所以不會關閉 socket 的輸入流與輸出流,程序會執行到內部 for 循環不斷循環。

  • 當運行客戶端並且關閉socket 的輸入輸出流時的輸出:

在兩端分別輸入 byebye 關閉輸入輸出流之後,當前socket被掃描出來並關閉。因為設置的該掃描線程為一個後台線程,當 Server 停止運行時,該線程也停止。

 

如有不對之處,還望指正,謝謝(●'◡'●)

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved