实现多人的聊天功能并能@的功能
分析: 实现多人的群聊功能,服务器端必须能够记录所有人的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;
}
@Override
public 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对应的Socket
map.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;
}
@Override
public 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();
}
}
}
}