目录
一、需求分析
1.首先该聊天室是基于网络编程以及多线程的,所以要有客户端与服务器的交互过程,同时应为多线程的加入允许多人登录聊天。
2.其次,聊天室是多人的。所以要实现颧髎和私聊两种聊天模式。
二、业务逻辑以及要构建的类的分析
1.UserLogin类
首先用户需要进行登录,所以我们要创建一个userlogin进行用户信息存储以及用户的登陆验证
代码如下:
public class UserLogin {
//登陆验证
public static boolean isLogin(String username, String password){
Map<String,String> usermap = is();
if (usermap.containsKey(username) && password.equals(usermap.get(username))){
System.out.println("登陆成功!!!");
return true;
}else {
System.out.println("登陆失败!!!");
return false;
}
}
//存储用户数据
private static Map<String,String> is(){
Map<String,String> userMap = new HashMap<>();
userMap.put("小张","123456");
userMap.put("小王","123456");
userMap.put("小刘","123456");
userMap.put("小李","123456");
return userMap;
}
}
2.KeHuDuan类
该类主要用于向服务器发出请求,并接收客户端协会的数据
代码如下:
public class KeHuDuan {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost",6667);
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = sc.next();
System.out.println("请输入密码:");
String password = sc.next();
//向服务器发送账号密码
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println(username+"-"+password);
pw.flush();
//接收服务器回写的信息
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String message = br.readLine();
if (Boolean.valueOf(message)){//如果登陆成功
chat(username);//开始聊天
}
}
private static void chat(String username) throws IOException {
//连接聊天服务器
Socket socket = new Socket("localhost",5874);
//向服务器发送用户信息
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println(username);
pw.flush();
//开启写线程任务
new WriteThread(socket).start();
//开启读线程任务
new ReadThread(socket).start();
}
}
3.ChatServer类
该类用来和客户端交互
代码如下:
public class ChatServer {
static Map<String, Socket> socketMap = new HashMap<>();
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(5874);
while (true){
System.out.println("聊天服务器已启动,等待客户端连接");
Socket socket = server.accept();
System.out.println("连接成功");
//接收客户端发送的用户信息
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String username = br.readLine();
System.out.println("读取到的用户名:"+username);
socketMap.put(username,socket);
//开启聊天线程任务
new ChatThread(socket).start();
}
}
}
4.ChatThread类
该类是本项目的核心类,编写了群聊和私聊的的业务
代码如下:
public class ChatThread extends Thread{
private Socket socket;
public ChatThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
while (true){
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String message = br.readLine();
System.out.println("读到的内容"+message);
String[] values = message.split("-");
Map<String,Socket> socketMap = ChatServer.socketMap;
Set<String> keyset = socketMap.keySet();
//长度为1是群聊
if (values.length == 1){
for (String username : keyset){
Socket socket1 = socketMap.get(username);
//向除了自己以外的其他人发送消息
if (socket1 != socket){
OutputStream os = socket1.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println(message);
pw.flush();
}
}
}else {
//获取用户名
String username = values[0];
//私聊
//获取对应的客户端通道
Socket socket2 = socketMap.get(username);
OutputStream os = socket2.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println(values[1]);
pw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5.LoginServer
登陆服务器 用于登录
代码如下:
public class LoginServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(6667);
while (true) {
System.out.println("登录服务器已启动,等待客户端连接");
Socket socket = server.accept();
System.out.println("连接成功");
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String message = br.readLine();
System.out.println("message"+message);
String[] values = message.split("-");//拆分
String username = values[0];
String password = values[1];
System.out.println(username+":"+password);
boolean flag = UserLogin.isLogin(username,password);
System.out.println("flag"+flag);
//回写信息
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println(flag+"");
pw.flush();
}
}
}
6.ReadThread类
该类用于客户端读操作
代码如下:
public class ReadThread extends Thread{
private Socket socket;
public ReadThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
while (true){
//读取信息
try {
InputStream is = socket.getInputStream();
BufferedReader br =new BufferedReader( new InputStreamReader(is));
String message = br.readLine();
System.out.println("客户端读到的消息"+message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
7.WriteThread类
该类用于客户端写操作
代码如下:
public class WriteThread extends Thread{
private Socket socket;
public WriteThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
Scanner sc = new Scanner(System.in);
while (true){
//写出消息
try {
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
System.out.println("请输入聊天内容");
String message = sc.next();
pw.println(message);
pw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
8.总结
首先,用户登录,客户端向登陆服务器发送请求
然后登陆服务器将进行登陆验证,若验证通过向客户端发送登陆成功i信号。
客户端收到登录成功信号后,想聊天服务器发出聊天请求
聊天服务器开启聊天线程
聊天线程进行群聊还是私聊的判定
三、总结
该项目融合了网络编程、多线程、集合、以及转化流等知识点,代码并不难,主要是弄清楚其中的业务逻辑,以及客户端和服务器的交互过程。
四、注意
该项目测试时 直接输入聊天内容判定为群聊
姓名-聊天内容 的格式为私聊
测试时要讲客户端窗口多开 同时登陆多个用户方可看到效果