这有点爽的

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

  之前只能有一个客户端接入,因为服务器只会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端

 

posted @ 2014-01-18 12:22  Chihane  阅读(147)  评论(0编辑  收藏  举报