zoukankan      html  css  js  c++  java
  • Java SE ——TCP协议网络编程(三)

    之前的代码中关闭了 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 停止运行时,该线程也停止。

    如有不对之处,还望指正,谢谢(●'◡'●)

  • 相关阅读:
    P2176 [USACO14FEB]路障Roadblock
    洛谷 P1187 3D模型
    洛谷 P2777 [AHOI2016初中组]自行车比赛
    洛谷P2896 [USACO08FEB]一起吃饭Eating Together
    洛谷P2983 [USACO10FEB]购买巧克力Chocolate Buying
    洛谷 P2858 [USACO06FEB]奶牛零食Treats for the Cows
    Restaurant
    OR in Matrix
    poj 3321Apple Tree
    Codeforces Round #204 (Div. 2) C. Jeff and Rounding
  • 原文地址:https://www.cnblogs.com/linlin0/p/6289679.html
Copyright © 2011-2022 走看看