内容
使用Socket模拟私聊群聊功能
具体内容
1.使用接口定义聊天的规范
public interface ChatProtocol {
//登录
String LOGIN_FLAG = "u+";
//私聊
String PRIVATE_FLAG = "p+";
//群聊
String PUBLIC_FLAG = "a+";
//分隔符
String SPLIT_FLAG = "♥";
//成功的状态
String SUCCESS = "1";
String FAILURE = "-1";
}
2.创建一个类管理用户
管理所有的登录的用户Map
判断某个用户是否已经登陆
public class UserManager {
//保存所有用户信息
private Map users = new HashMap<>();
/**
* 判断用户是否已经登录
*/
public boolean isLoogined(String name) {
//遍历数组
for (String key : users.keySet()) {
if (key.equals(name)) {
return true;
}
}
return false;
}
/**
* 保存当前登录的用户信息
*/
public void save(String name, Socket socket) {
users.put(name, socket);
}
/**
* 通过用户名找到对应的socket
*/
public Socket socketByName(String name) {
return users.get(name);
}
/**
* 通过socket对象找到对应的名称
*/
public String nameBySocket(Socket socket) {
for (String key : users.keySet()) {
//取出这个key对应的socket
if (socket == users.get(key)) {
return key;
}
}
return null;
}
/**
* 获取所有人的socket对象
*/
public Collection allUsers(){
return users.values();
}
}
3.服务器端和服务器端的子线程
服务器端
public class Server {
//用于保存每一个用户对应的姓名和socket
public static UserManager userManager = new UserManager();
public static void main(String[] args) {
try (ServerSocket ss = new ServerSocket(8888)) {
//监听所有来连接的客户端
while (true) {
Socket socket = ss.accept();
//让子线程处理这个socket
new ServerThread(socket).start();
}
} catch (IOException e) {
}
}
}
服务器端的子线程 继承于Thread
class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader br;
PrintStream ps;
//登录
//1.得到对应的输入流对象
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//得到对应的输出流
ps = new PrintStream(socket.getOutputStream());
String line;
while ((line = br.readLine()) != null) {
//登录 u+ u+
if (line.startsWith(ChatProtocol.LOGIN_FLAG) && line.endsWith(ChatProtocol.LOGIN_FLAG)) {
String[] items = line.substring(2).split("u+");
String name = items[0];
//获取名字
String neme = line.substring(2, line.length() - 2);//不包含这一个所以要取到下一个
//判断这个用户是否已经登录
if (Server.userManager.isLoogined(name)) {
//登录过了
ps.println((ChatProtocol.FAILURE));
} else {
//没有登录
//保存当前登录的用户信息
ps.println(ChatProtocol.SUCCESS);
}
}
//判断是不是私聊
else if (line.startsWith(ChatProtocol.PRIVATE_FLAG) && line.endsWith(ChatProtocol.PRIVATE_FLAG)) {
//p+jack♥hellop+
//获取信息
String msg = line.substring(2, line.length() - 2);
//分割 jack hello
String[] items = msg.split(ChatProtocol.SPLIT_FLAG);
//用户名
String name = items[0];
//聊天内容
String message = items[1];
//通过用户名找到对应的socket
Socket desSocket = Server.userManager.socketByName(name);
PrintStream desPs = new PrintStream(desSocket.getOutputStream());
//获取当前用户的名称
String currentName = Server.userManager.nameBySocket(socket);
//发送私聊消息
desPs.println(currentName + "向你发来私聊" + message);
} else {
String m = line.substring(2, line.length() - 2);
String curerntName = Server.userManager.nameBySocket(socket);
//遍历所有的用户信息
Collection sockets = Server.userManager.allUsers();
;
for (Socket s : sockets) {
PrintStream tempps = new PrintStream(s.getOutputStream());
tempps.println(curerntName+"发来群聊:"+m);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.客户端和客户端子线程
客户端
public class Client {
public static void main(String[] args) {
//连接服务器
BufferedReader br = null;
PrintStream ps = null;
BufferedReader brServer = null;
try (Socket socket = new Socket("127.0.0.1", 8888)) {
//登录
//发给服务器端的输出流
ps = new PrintStream(socket.getOutputStream());
//接收终端输入流
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//接收服务器端的输入流
brServer = new BufferedReader(new InputStreamReader(System.in));
while (true) {
//接收终端输入信息
String name = JOptionPane.showInputDialog("请输入用户名");
//拼接登陆格式
String loginStr = ChatProtocol.LOGIN_FLAG + name + ChatProtocol.LOGIN_FLAG;
//发送给服务器端
ps.println(loginStr);
//接收服务器端返回的结果
//判断登录结果
if (br.readLine().equals(ChatProtocol.SUCCESS)) {
System.out.println("登录成功");
break;
} else {
System.out.println("用户名已存在 请重新登录");
}
}
//登录成功
//开启线程处理服务器端的输入
new ClientThread(socket).start();
//接收终端输入 发送给服务器端
String line;
while ((line = br.readLine()) != null) {
//发送给服务器
ps.println(line);
}
} catch (IOException e) {
}
}
}
客户端子线程
class ClientThread extends Thread {
private Socket socket;
public ClientThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错");
} finally {
try {
if (br != null) {
br.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5.聊天实现的效果