1.功能:通过socket实现多个人群聊、私聊的功能;效果如图。
2.java代码
服务器端:
/** * FileName:ChatServer.java * @author zhanggw * @date 2018年1月26日 下午10:04:44 */ package com.kenick.chat; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * 聊天服务器启动程序 * @author zhanggw * @date 2018年1月26日 下午10:04:44 */ public class ChatServer { // 存储所有服务器和客户端的socket连接 public static Map<String,Socket> clientMap = Collections.synchronizedMap(new HashMap<String, Socket>()); public static void main(String[] args) { ServerSocket serverSocket = null; try { // 服务器启动,绑定本地端口5555 serverSocket = new ServerSocket(5555); System.out.println("启动服务器完成!"); // 开始不断接受客户端socket连接 while(true){ Socket clientSocket = serverSocket.accept(); new Thread(new ChatServerProcessThread(clientSocket)).start(); } } catch (Exception e) { e.printStackTrace(); }finally{ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
/** * FileName:ChatServerProcessThread.java * @author zhanggw * @date 2018年1月26日 下午10:05:12 */ package com.kenick.chat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.Iterator; import java.util.Set; /** * 聊天服务器多线程处理类 * @author zhanggw * @date 2018年1月26日 下午10:05:12 */ public class ChatServerProcessThread implements Runnable{ private Socket clientSocket; // 与客户端的socket连接 private BufferedReader clientBufferedReader; // 封装clientSocket public ChatServerProcessThread(Socket clientSocket) throws Exception{ this.clientSocket = clientSocket; this.clientBufferedReader = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream())); } @Override public void run() { String content = ""; // 接受的内容 try { while((content=this.clientBufferedReader.readLine())!=null){ try { String[] clientArray = content.split(":"); String sendId = clientArray[0]; // 发送人id String receiveId = clientArray[1]; // 接收人id String sendMsg = clientArray[2]; // 发送内容 if("register".equals(receiveId)){ // 注册并存储建立的socket连接 ChatServer.clientMap.put(sendId, this.clientSocket); }else if("all".equals(receiveId)){ // 群聊,发送给所有人 Set<String> keySet = ChatServer.clientMap.keySet(); Iterator<String> keyIterator = keySet.iterator(); while(keyIterator.hasNext()){ String clientId= keyIterator.next(); if(!sendId.equals(clientId)){ Socket clientSocket = ChatServer.clientMap.get(clientId); PrintStream ps = new PrintStream(clientSocket.getOutputStream()); ps.println(sendId+":"+sendMsg); ps.flush(); } } }else{ // 私聊,发送给指定人 Set<String> keySet = ChatServer.clientMap.keySet(); Iterator<String> keyIterator = keySet.iterator(); while(keyIterator.hasNext()){ String clientId= keyIterator.next(); if(clientId.equals(receiveId)){ Socket clientSocket = ChatServer.clientMap.get(clientId); PrintStream ps = new PrintStream(clientSocket.getOutputStream()); ps.println(sendId+":"+sendMsg); ps.flush(); } } } } catch (Exception e) { // 暂时隐去异常处理 //e.printStackTrace(); } } } catch (IOException e) { // 暂时隐去异常处理 // e.printStackTrace(); } } }客户端:
/** * FileName:ChatClient.java * @author zhanggw * @date 2018年1月26日 下午10:18:53 */ package com.kenick.chat; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; /** * 聊天客户端启动程序 * @author zhanggw * @date 2018年1月26日 下午10:18:53 */ public class ChatClient { public static void main(String[] args) { try { String content = null; // 接收从命令行输入的信息 String clientId = "anonymous"; // 默认账号 Socket serverSocket = new Socket("127.0.0.1",5555); new Thread(new ChatClientProcessThread(serverSocket)).start(); PrintStream ps = new PrintStream(serverSocket.getOutputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("注册你的账号:"); if((content = br.readLine())!=null){ if(!"".equals(content)){ clientId = content; System.out.println("账号注册成功!账号ID:"+clientId); }else{ clientId = clientId+System.currentTimeMillis(); System.out.println("账号未注册成功,使用匿名账号:"+clientId); } ps.println(clientId+":register"+":newAccount"); ps.flush(); } // 开始循环接收输入信息,并发送给服务器 while((content=br.readLine())!=null){ ps.println(clientId+":"+content); ps.flush(); } } catch (Exception e) { e.printStackTrace(); } } }
/** * FileName:ChatClientProcessThread.java * @author zhanggw * @date 2018年1月26日 下午10:19:36 */ package com.kenick.chat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; /** * 聊天客户端多线程处理类 * @author zhanggw * @date 2018年1月26日 下午10:19:36 */ public class ChatClientProcessThread implements Runnable{ private Socket serverSocket; // 与服务器的socket连接 private BufferedReader serverReader; // 对serverSocket的封装 public ChatClientProcessThread(Socket serverSocket) throws Exception{ this.serverSocket = serverSocket; this.serverReader = new BufferedReader(new InputStreamReader(serverSocket.getInputStream())); } @Override public void run() { String content = null; try { while((content=this.serverReader.readLine())!=null){ System.out.println(content); } } catch (Exception e) { e.printStackTrace(); }finally{ try { this.serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }