【JAVA】基于socket的无GUI聊天室

其实Socket这个问题困扰我好久了,一直没有好好梳理过,今天花了一天的时间,看了很多资料,写了一个基于Socket的无GUI聊天室,算是对Socket的一个总结吧。

 

关于Socket和SocketServer,这里就不多解释了。直接看图。

 

说明几点:

  • accept是阻塞式的,它会一直等待Client的连接,直到有Client连接时,accept之后的代码才会被执行。
  • 输入输出流的选择可以有很多方式,建议选择DataInputStream和DataOutputStream,因为DataInputStream在读取内容时,直接一个readUTF就可以了,可以省去很多不必要的麻烦。

思路:

  • 服务端:
    • 考虑到接入的客户端不只一个,因此服务端需要一个List来装接入的Socket连接。一个连接代表一个Client。
    • 启动两个线程。一个线程用于接收接入的Client,另一个线程用于接收Client发来的消息,并将消息发送给所有Client(本质即迭代List)。
  • 客户端:
    • 客户端也需要启动两个线程。一个线程用于接收Server发来的消息(实际上是别的Client发给Server,Server转发过来的)。另一个线程用于像Server发送消息。
  • 其它:
    • 需要注意关闭socket时抛异常的情况(因为一个线程还在不停的等待读取信息)。
    • 至于两个线程怎么开,自由度很大,可以自己决定。

Server端代码:

 1 package com.ryan.chatRoom;
 2 
 3 import java.io.DataInputStream;
 4 import java.io.DataOutputStream;
 5 import java.io.IOException;
 6 import java.net.ServerSocket;
 7 import java.net.Socket;
 8 import java.util.ArrayList;
 9 import java.util.List;
10 import java.util.concurrent.ExecutorService;
11 import java.util.concurrent.Executors;
12 
13 public class Server1 {
14 
15     private List<Socket> socketList;
16     private Socket socket;
17     private ServerSocket server;
18     private ExecutorService service;
19     private DataOutputStream dos;
20 
21     public Server1() throws IOException {
22 
23         server = new ServerSocket(10000);
24         socketList = new ArrayList<>();
25         service = Executors.newCachedThreadPool();
26 
27         System.out.println("waiting for client...");
28         while (true){
29             socket = server.accept();
30             socketList.add(socket);
31             System.out.println("Client comes...total:" + socketList.size());
32             dos = new DataOutputStream(socket.getOutputStream());
33             dos.writeUTF("message from server: connect successfully");
34             //dos.close();
35             service.execute(new ServerThread(socket));
36 
37         }
38     }
39 
40     private class ServerThread implements Runnable{
41         Socket socket;
42         DataOutputStream dos;
43         DataInputStream dis;
44         String textFromClient;
45 
46         public ServerThread(Socket socket) throws IOException {
47             this.socket = socket;
48             dis = new DataInputStream(socket.getInputStream());
49         }
50 
51 
52         @Override
53         public void run() {
54             try {
55                 while ((textFromClient=dis.readUTF())!=null){
56                     if(textFromClient.equals("exit")){
57                         //socket.close();
58                         socketList.remove(socket);
59                         //dis.close();
60                         //dos.close();
61                         System.out.println("client leaves...current client:" + socketList.size());
62                     }else {
63                         for (Socket socket : socketList) {
64                             dos = new DataOutputStream(socket.getOutputStream());
65                             dos.writeUTF(textFromClient);
66                         }
67                     }
68                 }
69             } catch (IOException e) {
70 
71             }
72         }
73     }
74 
75     public static void main(String[] args) throws IOException {
76         new Server1();
77     }
78 }
View Code

 

Client端代码:

 1 package com.ryan.chatRoom;
 2 
 3 import java.io.DataInputStream;
 4 import java.io.DataOutputStream;
 5 import java.io.IOException;
 6 import java.net.Socket;
 7 import java.util.Scanner;
 8 import java.util.concurrent.Executor;
 9 import java.util.concurrent.ExecutorService;
10 import java.util.concurrent.Executors;
11 
12 
13 public class Client1 {
14 
15     private Socket socket;
16     private Scanner scanner;
17     private DataInputStream dis;
18     private DataOutputStream dos;
19     private String textFromServer;
20     private ExecutorService services;
21 
22     public Client1() {
23         try {
24             socket = new Socket("127.0.0.1", 10000);
25             dis = new DataInputStream(socket.getInputStream());
26             System.out.println(dis.readUTF());
27             services = Executors.newCachedThreadPool();
28             services.execute(new ClientThread(socket));
29 
30             while ((textFromServer = dis.readUTF()) != null) {
31                 System.out.println("message from Server:" + textFromServer);
32             }
33         } catch (IOException e) {
34             System.out.println("see you");
35             System.exit(0);
36         }
37 
38     }
39 
40     private class ClientThread implements Runnable {
41 
42         Scanner scanner;
43         DataOutputStream dos;
44         Socket socket;
45         String sendToServer;
46 
47         public ClientThread(Socket socket) throws IOException {
48             this.socket = socket;
49             dos = new DataOutputStream(socket.getOutputStream());
50             scanner = new Scanner(System.in);
51         }
52 
53         @Override
54         public void run() {
55             while (true) {
56                 try {
57                     sendToServer = scanner.nextLine();
58                     dos.writeUTF(sendToServer);
59                     if(sendToServer.equals("exit")){
60                         socket.close();
61                         dos.close();
62                         dis.close();
63                         services.shutdown();
64                     }
65                 } catch (IOException e) {
66                     System.out.println("see you!");
67                     System.exit(0);
68                 }
69             }
70         }
71     }
72 
73     public static void main(String[] args) throws IOException {
74         new Client1();
75     }
76 }
View Code

 

 

注意事项:

  • 先启动Server端,再启动Client端。
  • Server端只能启动一个,Client端可以启动多个。

 

-----------------------------------------------------

请尊重作者劳动成果,

转载请注明出处:http://www.cnblogs.com/ryanyu/p/6669030.html

posted @ 2017-04-05 15:46  加勒比海龟  阅读(298)  评论(0编辑  收藏  举报