一:需求分析
1:聊天室:一个服务器,多个客户端,当一个客户端发送信息给服务器时,服务器会把
消息广播给其他的客户端用户。
2:服务器端,主线程一直处于阻塞状态,接受客户端请求,每当一个客户端发送请求过来
时,都会启动一个线程处理请求。
3:客户端,主线程负责向服务器通过控制台写数据,另外启动一个线程负责读取服务器端发送
过来的信息。
二:服务器端
1 /** 2 * 3 */ 4 package com.hlcui.socket; 5 6 import java.io.BufferedReader; 7 import java.io.IOException; 8 import java.io.InputStreamReader; 9 import java.io.PrintWriter; 10 import java.net.InetAddress; 11 import java.net.ServerSocket; 12 import java.net.Socket; 13 import java.util.ArrayList; 14 import java.util.Collections; 15 import java.util.List; 16 17 /** 18 * @author Administrator 19 * 20 */ 21 public class MyServer { 22 public static final int PORT = 8080; 23 public static List<Socket> socketList = Collections 24 .synchronizedList(new ArrayList<Socket>()); // 定义一个线程安全的list 25 26 // 初始化 27 public void init() { 28 29 try { 30 ServerSocket ss = new ServerSocket(PORT); 31 System.out.println("服务已经启动,等待客户端连接..."); 32 // 主线程一直在监听端口 33 while (true) { 34 Socket s = ss.accept(); 35 InetAddress inet = s.getInetAddress(); 36 System.out.println(inet.getHostAddress()+"上线了"); 37 socketList.add(s); 38 new Thread(new ServerThread(s)).start(); // 启动线程处理客户端请求 39 } 40 } catch (IOException e) { 41 e.printStackTrace(); 42 } 43 } 44 45 public static void main(String[] args) { 46 MyServer server = new MyServer(); 47 server.init(); 48 } 49 } 50 51 class ServerThread implements Runnable { 52 private BufferedReader br; 53 private Socket s; 54 55 ServerThread(Socket s) throws IOException { 56 this.s = s; 57 br = new BufferedReader(new InputStreamReader(s.getInputStream())); 58 } 59 60 @Override 61 public void run() { 62 String line = null; 63 while ((line = readClientContext()) != null) { 64 System.out.println(line); 65 // 将客户端数据广播出去(传递给每个客户端数据) 66 for (Socket s : MyServer.socketList) { 67 try { 68 PrintWriter pw = new PrintWriter(s.getOutputStream()); 69 pw.println(line); 70 pw.flush(); 71 //pw.close(); //这里的pw一定不能关闭 72 } catch (IOException e) { 73 e.printStackTrace(); 74 } 75 } 76 } 77 } 78 79 // 读取客户端数据 80 private String readClientContext() { 81 try { 82 return br.readLine(); 83 } catch (IOException e) { 84 MyServer.socketList.remove(s); 85 System.out.println("读取客户端数据失败!"); 86 } 87 return null; 88 89 } 90 91 }
三:客户端
1 /** 2 * 3 */ 4 package com.hlcui.socket; 5 6 import java.io.BufferedReader; 7 import java.io.IOException; 8 import java.io.InputStreamReader; 9 import java.io.PrintStream; 10 import java.net.Socket; 11 12 /** 13 * @author Administrator 14 * 15 */ 16 public class MyClient { 17 public static final String IP = "127.0.0.1"; 18 public static final int PORT = 8080; 19 20 // 初始化 21 public void init() { 22 BufferedReader br = null; 23 PrintStream ps = null; 24 try { 25 Socket s = new Socket(IP, PORT); 26 // 启动线程读取服务器端发送的数据 27 new Thread(new ClientThread(s)).start(); 28 // 控制台向服务器发送数据 29 br = new BufferedReader(new InputStreamReader(System.in)); 30 ps = new PrintStream(s.getOutputStream()); 31 String line = null; 32 while ((line = br.readLine()) != null) { 33 ps.println(line); 34 } 35 ps.flush(); 36 } catch (IOException e) { 37 e.printStackTrace(); 38 } finally { 39 if (br != null) { 40 try { 41 br.close(); 42 } catch (IOException e) { 43 e.printStackTrace(); 44 } 45 } 46 if (ps != null) { 47 ps.close(); 48 } 49 } 50 } 51 52 public static void main(String[] args) { 53 MyClient client = new MyClient(); 54 client.init(); 55 } 56 57 } 58 59 class ClientThread implements Runnable { 60 private BufferedReader br; 61 62 ClientThread(Socket s) { 63 try { 64 br = new BufferedReader(new InputStreamReader(s.getInputStream())); 65 } catch (IOException e) { 66 e.printStackTrace(); 67 } 68 } 69 70 @Override 71 public void run() { 72 String line = null; 73 try { 74 while ((line = br.readLine()) != null) { 75 System.out.println(line); 76 } 77 } catch (IOException e) { 78 e.printStackTrace(); 79 } 80 } 81 82 }