• 这有点爽的


      简单应用了一下多线程,搞定了多客户端的问题。

      之前只能有一个客户端接入,因为服务器只会accept()一次,然后就进入接收输入流的死循环了。

      然后我趴在地上想了一下,主进程里死循环来accept(),然后每个客户端new一个新进程是不是就搞定了,越想越觉得有道理,于是就试了试。

      另外每个进程里重新各new一个Socket和输入流,这样就不会跟主进程产生冲突,同时主进程里的这两个也就可以直接删掉了。

      于是现在是各个进程各自处理自己的接收信息动作,互不干涉。

      启动进程是start()不是run()哪。

      现在的问题是服务器已经把该接收的都接收了,怎么把客户端发上来的消息再发给其他客户端呢。

      不可能在服务器里放一个StringBuffer,虽然这样很稳妥,也能解决问题,但是这样消耗带宽越来越大……

      另一种方法是客户端发上来消息之后先不更新自己的文本框内容,由服务器向所有客户端来发送,也就是说我发一条消息要发上去再下下来,是不是有点蛋疼,虽然这样也可以解决问题。

      

      诸君,我从小学开始就最擅长找笨办法了……

      智商低好痛苦 _(:з」∠)_

      1 import java.io.*;
      2 import java.net.*;
      3 
      4 /**
      5  * 服务器端,目前还是单纯的解包并在命令行打印,再下个版本改。
      6  * 1. 处理了端口已占用的异常。
      7  * 2. 客户端退出后不关闭进程。
      8  * 3. *重要内容* 改用多进程的方式,支持了多客户端接入。
      9  * 不过目前只能接收信息命令行打印。
     10  * 之后加上向其他客户端发送消息的功能。
     11  * 
     12  * @author mlxy
     13  * @version 0.6
     14  * */
     15 public class SimChatServer {
     16     ServerSocket ss = null;
     17     int users;
     18     
     19     /** 服务器构造方法,只用来初始化已连接客户端数。*/
     20     public SimChatServer() {users = 0;}
     21     
     22     public static void main(String[] args) {
     23         SimChatServer server = new SimChatServer();
     24         
     25         // 尝试启动服务器,端口被占用则提示并退出。
     26         try {
     27             server.ss = new ServerSocket(2333);
     28         } catch (BindException e) {
     29             System.out.println("Port occupied.");
     30             System.exit(0);
     31         } catch (IOException ex) {
     32             ex.printStackTrace();
     33         }
     34 
     35         // 死循环,等待客户端连接,连接成功则启动一个新线程。
     36         try {
     37             do {
     38                 server.new ClientThread(server, server.ss.accept()).start();
     39                 server.users++;
     40                 System.out.println("Current clients: " + server.users);
     41             } while (server.users > 0);
     42             
     43         } catch (IOException e) {
     44             e.printStackTrace();
     45         }
     46         
     47         
     48     }
     49     
     50     /** 管理客户端退出的方法。*/
     51     private void clientOut() {
     52         users--;
     53         System.out.println("Current clients: " + users);
     54         
     55         // 所有客户端都断开之后关闭服务器。
     56         if (users == 0) {
     57             System.out.println("All clients are out, server abort.");
     58             try {
     59                 ss.close();
     60             } catch (IOException e) {
     61                 e.printStackTrace();
     62             }
     63         }
     64     }
     65     
     66     /**
     67      * 内部类。
     68      * 单个客户端线程,包含了处理客户端发来信息的方法。
     69      * 目前只能接收信息,之后再加上向客户端发包的功能。
     70      * 
     71      * @author mlxy
     72      * @version 0.5
     73      */
     74     class ClientThread extends Thread {
     75         SimChatServer server;
     76         Socket singleSocket;
     77         ObjectInputStream singleInput;
     78         
     79         /** 一个客户端线程的构造方法。*/
     80         public ClientThread(SimChatServer server, Socket singleSocket) {
     81             this.server = server;
     82             this.singleSocket = singleSocket;
     83             System.out.println("Client connected.");
     84             try {
     85                 singleInput = new ObjectInputStream(singleSocket.getInputStream());
     86             } catch (IOException e) {
     87                 e.printStackTrace();
     88             }
     89         }
     90 
     91         @Override
     92         public void run() {
     93             // 主运行部分,抓到客户端退出的异常就打印提示并退出。
     94             try {
     95                 // 死循环,读包拆包打印。
     96                 while (true) {
     97                     String[] packReceived = (String[]) singleInput.readObject();
     98                     System.out.println(packReceived[0] + ": " + packReceived[1]);
     99                 }
    100                     
    101             } catch (ClassNotFoundException e) {
    102                 e.printStackTrace();
    103             } catch (EOFException ex) {
    104                 System.out.println("Client disconnected.");
    105             } catch (IOException exc) {
    106                 exc.printStackTrace();
    107             } finally {
    108                 // 关闭所有引用,释放资源。
    109                 try {
    110                     if (singleSocket != null)
    111                         singleSocket.close();
    112                     if (singleInput != null)
    113                         singleInput.close();
    114                     
    115                     // 报告一个客户端退出。
    116                     server.clientOut();
    117                 } catch (IOException e) {
    118                     e.printStackTrace();
    119                 }
    120             }
    121         }
    122         
    123     }
    124 }
    Server端
  • 相关阅读:
    CF353D Queue(结论)
    CF1147C Thanos Nim(博弈论、结论推导)
    牛客:CBX and children(平衡树+二分+贪心)
    牛客:Gambling Monster(权值线段树+离散化+离线)
    剑指49.把字符串转换成整数
    剑指48.不用加减乘除做加法
    剑指47.求1+2+3+...+n
    剑指46.孩子们的游戏(圆圈中最后剩下的数字)
    剑指45.扑克牌顺子
    剑指44.翻转单词顺序
  • 原文地址:https://www.cnblogs.com/chihane/p/3524975.html
Copyright © 2020-2023  润新知