Java学习记录(六):控制台聊天室
1、题目及素材来源
题目来自于BILIBILI黑马程序员官方Java基础教程,具体包括原始代码以及相关素材,相关业务逻辑的实现根据教程的要求自己独立实现。详细功能需求以及相关要求可自行观看其对应教程。
主要是利用TCP协议创建一个客户端和服务器端,然后可以同时启动多个客户端,同时利用服务器进行判断客户端是否能够成功登录,然后实现各个客户端消息的转发,最终实现控制台版本的聊天室。
2、整体效果
(1)客户端主页面
(2)客户端注册
(3)客户端登录(只展示一个客户端)
(4)服务器端提示信息
(5)开始聊天
3、各个功能简要介绍
(1)游戏登录、注册
主要是在客户端实现,首先打印一个菜单包括登录和注册选项。选择登录并输入账号密码后,将数据发送到服务器进行判断是否存在账号,且密码正确,实现登录逻辑。选择注册并正确输入账号密码后将账号密码发送至服务器判断是否已经存在当前账号,若不存在则创建。
(2)聊天
先启动服务器,再同时启动多个客户端并登录至系统即可开始聊天。当一个客户端发送了一条消息时,服务器将接受到当前消息并将其转发至所有客户端,进而实现了聊天器功能。
4、各文件完整代码
(1)用户信息Java bean类
package com.test.bean;
public class UserInfo {
private String username;
private String password;
public UserInfo() {
}
public UserInfo(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "UserInfo{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
(2)客户端自定义线程类
package com.test.thread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClientRunnable implements Runnable {
Socket socket;
public ClientRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
while (true) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String response = br.readLine();
System.out.println(response);
//System.out.println("请输入聊天内容, 回车发送: ");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
(3)服务器自定义线程类
package com.test.thread;
import com.test.Server;
import com.test.bean.UserInfo;
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
public class LoginRunnable implements Runnable{
Socket socket;
ArrayList<UserInfo> userList;
public LoginRunnable(Socket socket){
this.socket = socket;
this.userList = new ArrayList<>();
try {
BufferedReader br = new BufferedReader(new FileReader("data\\userInfo.txt"));
String str;
while ((str = br.readLine()) != null) {
String username = str.split("&")[0].split("=")[1];
String password = str.split("&")[1].split("=")[1];
userList.add(new UserInfo(username, password));
}
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
String choice = br.readLine();
switch (choice) {
case "login" -> {
System.out.println("用户登录");
String content = br.readLine();
String username = content.split("&")[0].split("=")[1];
String password = content.split("&")[1].split("=")[1];
System.out.println(content);
//br.close();
String flag = "-1";
for (UserInfo user : userList) {
if (username.equals(user.getUsername()) && password.equals(user.getPassword())) {
flag = "1";
} else if (username.equals(user.getUsername()) && !password.equals(user.getPassword())) {
flag = "0";
}
}
System.out.println("开始返回数据");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(flag);
bw.newLine();
bw.flush();
System.out.println("返回成功");
//bw.close();
if ("1".equals(flag)) {
Server.socketList.add(socket);
chat(br, username);
}
}
case "register" -> {
System.out.println("用户注册");
String content = br.readLine();
String username = content.split("&")[0].split("=")[1];
String password = content.split("&")[1].split("=")[1];
System.out.println(content);
int flag = 1;
for (UserInfo user : userList) {
if (user.getUsername().equals(username)) {
flag = 0;
break;
}
}
if (!username.matches("[A-Za-z]{6,18}") || !password.matches("[A-Za-z][0-9]{2,7}")) {
flag = -1;
}
if (flag == 1) {
userList.add(new UserInfo(username, password));
BufferedWriter bw = new BufferedWriter(new FileWriter("data\\userInfo.txt"));
for (UserInfo user : userList) {
bw.write("username=" + user.getUsername() + "&password=" + user.getPassword());
bw.newLine();
bw.flush();
}
bw.close();
}
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(String.valueOf(flag) );
bw.newLine();
bw.flush();
}
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void chat(BufferedReader br, String username) throws IOException {
while (true) {
String message = br.readLine();
System.out.println(username+": "+message);
for (Socket s : Server.socketList) {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bw.write(username+": "+message);
bw.newLine();
bw.flush();
}
}
}
}
(4)Client类
package com.test;
import com.test.thread.ClientRunnable;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
Socket socket = new Socket("127.0.0.1", 10086);
while (true){
mainMenu();
String str = scanner.nextLine();
if (!str.matches("[0-9]")){
System.out.println("输入错误, 请重新输入!\n");
continue;
}
int choice = Integer.parseInt(str);
switch (choice){
case 1 -> {
boolean result = login(socket);
if (result){
new Thread(new ClientRunnable(socket)).start();
chat(socket);
} else {
continue;
}
}
case 2 -> {
boolean result = register(socket);
//System.out.println(result);
}
default -> {
System.out.println("没有此选项, 请重新输入!\n");
continue;
}
}
}
}
public static boolean register (Socket socket){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入账号: ");
String username = scanner.nextLine();
System.out.println("请输入密码");
String password = scanner.nextLine();
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("register");
bw.newLine();
bw.flush();
bw.write("username=" + username+ "&password=" + password);
bw.newLine();
bw.flush();
//bw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String response = br.readLine();
//System.out.println(response);
if ("-1".equals(response)){
System.out.println("账号密码格式错误!\n");
return false;
} else if ("0".equals(response)){
System.out.println("账号已存在!\n");
return false;
} else if ("1".equals(response)){
System.out.println("注册成功!\n");
return true;
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public static void chat(Socket socket) throws IOException {
Scanner scanner = new Scanner(System.in);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
System.out.println("请输入聊天内容, 回车发送: ");
while (true){
String input = scanner.nextLine();
bw.write(input);
bw.newLine();
bw.flush();
}
}
public static boolean login(Socket socket){
//System.out.println("选择了登录");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入账号: ");
String username = scanner.nextLine();
System.out.println("请输入密码");
String password = scanner.nextLine();
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("login");
bw.newLine();
bw.flush();
bw.write("username=" + username+ "&password=" + password);
bw.newLine();
bw.flush();
//bw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String response = br.readLine();
//System.out.println(response);
if ("-1".equals(response)){
System.out.println("账号不存在, 登录失败!\n");
return false;
} else if ("0".equals(response)){
System.out.println("密码错误, 登录失败!\n");
return false;
} else if ("1".equals(response)){
System.out.println("登录成功!\n");
return true;
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public static void mainMenu(){
System.out.println("======欢迎来到聊天室======");
System.out.println("1、登录");
System.out.println("2、注册");
System.out.println("========================");
System.out.println("请输入您的选择: ");
}
}
(5)Server类
package com.test;
import com.test.thread.LoginRunnable;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.*;
public class Server {
public static ArrayList<Socket> socketList = new ArrayList<>();
public static void main(String[] args) throws IOException {
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 16, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(2), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
ServerSocket ss = new ServerSocket(10086);
while (true) {
System.out.println("等待客户端连接...");
Socket socket = ss.accept();
System.out.println("得到一个链接");
pool.submit(new LoginRunnable(socket));
}
}
}