实现多人的聊天功能并能@的功能
分析: 实现多人的群聊功能,服务器端必须能够记录所有人的socket套接字,本次代码操作中以map来存储用户的名字和套接字,然后对于每次接受的数据都群发一遍,对于@功能的实现,提炼出名字,找到对应的套接字然后回送数据。
服务端的实现:
package com.mixm0924;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.ServerSocket;import java.net.Socket;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;/*** @ClassName: Client01* @Description: 实现群聊并能解析@的功能* @author: Mixm* @date: 2015年9月28日 上午12:03:53*/public class Server01 {public static void main(String[] args) {// 用来存放socket和名字的对应关系 默认名字不能重复Map<String, Socket> map = null;ServerSocket ss = null;Socket s = null;try {map = new HashMap<String, Socket>();ss = new ServerSocket(10001);while (true) {s = ss.accept();new ServerThread(s, map).start();}} catch (Exception e) {e.printStackTrace();} finally {try {ss.close();} catch (IOException e) {e.printStackTrace();}}}}/*** @ClassName: ClientThread* @Description: 读取中默认第一次读取的是个文字,就要加入到map中,用名字作为键,对于有@的拆分,并且找到人物然后进行转发* @author: Mixm* @date: 2015年9月28日 上午12:25:10*/class ServerThread extends Thread {private Socket s = null;private Map<String, Socket> map = null;private String name = null;public ServerThread(Socket s, Map<String, Socket> map) {this.s = s;this.map = map;}@Overridepublic void run() {BufferedReader br = null;try {// 判断是否为第一次,第一次的数据默认为名字,flag 为true就代表要接受的是名字boolean flag = true;// 关联流br = new BufferedReader(new InputStreamReader(s.getInputStream()));while (true) {if (flag) {name = readLine(br);if (name == null) {break;}System.out.println(name + "加入聊天室");map.put(name, s);flag = false;} else {// 得到信息String msg_receive = readLine(br);if (name == null) {break;}// 判断是否为@if (msg_receive.startsWith("@")) {int index = msg_receive.indexOf(":");String temp_name = msg_receive.substring(1, index);String temp_msg = msg_receive.substring(index + 1);sendMsg(temp_msg, map.get(temp_name));} else {for (Socket s : map.values()) {sendMsg(msg_receive, s);}}}}} catch (Exception e) {e.printStackTrace();} finally {try {br.close();} catch (IOException e) {e.printStackTrace();}}}//为什么这个流不能关 找时间会解答一下private void sendMsg(String msg, Socket s) {SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");BufferedWriter bw = null;try {bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));bw.write(name + " " + sdf.format(new Date()) + " " + msg);bw.newLine();bw.flush();} catch (Exception e) {e.printStackTrace();}// finally {// try {// ///bw.close();//这个流 不能关 我很忧伤 不知道原因// } catch (IOException e) {// e.printStackTrace();// }// }}//这个函数是解决用户强行退出 会抛异常的问题public String readLine(BufferedReader br) {String msg = null;try {msg = br.readLine();} catch (Exception e) {// 说明有客户端退出System.out.println(name + "退出聊天室");// 从map集合里面移除name对应的Socketmap.remove(name);}return msg;}}
客户端代码:
package com.mixm0924;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.Socket;public class Client01 {public static void main(String[] args) {Socket s = null;// 用来读键盘BufferedReader br_input = null;BufferedWriter bw = null;try {s = new Socket("127.0.0.1", 10001);new ReadThread(s).start();br_input = new BufferedReader(new InputStreamReader(System.in));bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));String str = null;// 第一次提示输入名字System.out.println("请输入你的名字");while (true) {str = br_input.readLine();bw.write(str);bw.newLine();bw.flush();}} catch (Exception e) {e.printStackTrace();} finally {try {br_input.close();bw.close();s.close();} catch (IOException e) {e.printStackTrace();}}}}/*** @ClassName: ReadThread* @Description: 由于s.read是阻塞式方法 所以为了读的时候能写 就把读用线程在后台实现* @author: Mixm* @date: 2015年9月28日 上午12:54:23*/class ReadThread extends Thread {private Socket s = null;public ReadThread(Socket s) {this.s = s;}@Overridepublic void run() {BufferedReader br = null;try {br = new BufferedReader(new InputStreamReader(s.getInputStream()));String msg = null;while ((msg = br.readLine()) != null) {System.out.println(msg);}} catch (Exception e) {e.printStackTrace();} finally {try {br.close();} catch (Exception e2) {e2.printStackTrace();}}}}
1867

被折叠的 条评论
为什么被折叠?



