Java Socket聊天室功能
dreaming9420 人气:01 创建登录判断类UserLogin
import java.util.HashSet; import java.util.Set; public class UserLogin { public static boolean login(String username) { Set<String> set = initUser(); // set中含有该username则登录成功 return set.contains(username); } public static Set<String> initUser() { Set<String> set = new HashSet<>(); set.add("111"); set.add("222"); set.add("333"); set.add("444"); set.add("555"); return set; } }
2 创建登录服务器LoginServer
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class LoginServer { public static void main(String[] args) { int port = 6666; try (ServerSocket serverSocket = new ServerSocket(port)) { System.out.println("登录服务器已经启动"); while (true) { Socket socket = serverSocket.accept(); // 接收Client输出的信息(username) InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String username = bufferedReader.readLine(); // 调用登录方法,判断是否成功登录 OutputStream outputStream = socket.getOutputStream(); PrintStream printStream = new PrintStream(outputStream); if (UserLogin.login(username)) { System.out.println(username + "登录成功"); // 登录成功输出"true"到Client printStream.println("true"); } else { System.out.println(username + "登录失败"); // 登录失败则输出"false"到Client printStream.println("false"); } printStream.flush(); } } catch (IOException e) { e.printStackTrace(); } } }
3 创建聊天服务器ChatServer
import com.socket.socketChatroom.bio.thread.ChatThread; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map; public class ChatServer { // 保存当前聊天中的所有Map<username,Socket> public static Map<String, Socket> socketMap = new HashMap<>(); public static void main(String[] args) { int port = 9999; try (ServerSocket serverSocket = new ServerSocket(port)) { System.out.println("聊天服务器已经启动"); while (true) { Socket socket = serverSocket.accept(); // 接收Client输出的username InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String username = bufferedReader.readLine(); System.out.println(username + "连接到聊天服务器"); // 连接聊天服务器成功则将它的<username,Socket>放入socketMap中 socketMap.put(username, socket); System.out.println(socketMap); // 因为可能有多个Client与ChatServer进行交互,所以一旦有Client连接成功就新创建一个线程与之交互 new ChatThread(username,socket).start(); } } catch (IOException e) { throw new RuntimeException(e); } } }
4 创建客户端Client
import com.socket.socketChatroom.bio.thread.ReadThread; import com.socket.socketChatroom.bio.thread.WriteThread; import java.io.*; import java.net.Socket; import java.util.Scanner; public class Client { public static void main(String[] args) { // 服务端地址,端口号 String ip = "127.0.0.1";// 本机IP地址 int port = 6666; // 必须和LoginServer的端口一样 try { Socket client = new Socket(ip, port); Scanner scanner = new Scanner(System.in); System.out.println("请输入用户名"); String username = scanner.nextLine(); // 将用户名输出到LoginServer OutputStream outputStream = client.getOutputStream(); PrintStream printStream = new PrintStream(outputStream); printStream.println(username); printStream.flush(); // 接收LoginServer输出的是否登录成功标志("true"或"false") InputStream inputStream = client.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String state = bufferedReader.readLine(); // 如果为"true",则为登录成功,可以开始聊天 if (Boolean.parseBoolean(state)) { chat(username); } } catch (IOException e) { e.printStackTrace(); } } public static void chat(String username) { try { String ip = "127.0.0.1";// 本机IP地址 int port = 9999;// 必须和ChatServer的端口一样 // 连接聊天服务器ChatServer Socket socket = new Socket(ip, port); // 将username输出到ChatServer OutputStream outputStream = socket.getOutputStream(); PrintStream printStream = new PrintStream(outputStream); printStream.println(username); printStream.flush(); // 因为聊天的收发消息不一定是与同一个人,所以创建两个线程分别用于收和发 new ReadThread(socket).start(); new WriteThread(socket).start(); } catch (IOException e) { throw new RuntimeException(e); } } }
5 创建服务器用于处理聊天的线程类ChatThread
import com.socket.socketChatroom.bio.server.ChatServer; import java.io.*; import java.net.Socket; import java.util.HashSet; import java.util.Map; import java.util.Set; public class ChatThread extends Thread { private final String username; private final Socket socket; public ChatThread(String username, Socket socket) { this.username = username; this.socket = socket; } @Override public void run() { while (true) { try { // 接收Client的WriteThread线程输出的消息 InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String message = bufferedReader.readLine(); System.out.println(username + "说: " + message); // 将当前所有在线的Client的username存入usernameSet中 Map<String, Socket> socketMap = ChatServer.socketMap; Set<String> usernameSet = new HashSet<>(); for (Map.Entry<String, Socket> map : socketMap.entrySet()) { usernameSet.add(map.getKey()); } // 以"-"作为标识符,判断是群聊还是单聊 String[] values = message.split("-"); if (values.length == 2 && usernameSet.contains(values[0])) { //单聊 // values[0]为要指定发送的Client的username OutputStream outputStream = socketMap.get(values[0]).getOutputStream(); PrintStream printStream = new PrintStream(outputStream); // values[1]为消息内容 printStream.println(username + "说: " + values[1]); printStream.flush(); } else {//群聊 // 将消息发送到除自己之外的所有Client for (String username : usernameSet) { if (socket != socketMap.get(username)) { OutputStream outputStream = socketMap.get(username).getOutputStream(); PrintStream printStream = new PrintStream(outputStream); printStream.println(this.username + "说: " + message); printStream.flush(); } } } } catch (IOException e) { throw new RuntimeException(e); } } } }
6 创建客户端Client用于发送消息的线程类WriteThread
import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; public class WriteThread extends Thread { private final Socket socket; public WriteThread(Socket socket) { this.socket = socket; } @Override public void run() { while (true) { try { // 获取输出流 OutputStream outputStream = socket.getOutputStream(); PrintStream printStream = new PrintStream(outputStream); // 键盘输入要发送的消息,若为单聊,则以要发送的Client的username+"-",开头,比如"111-hello",表示向111这个Client发送"hello" Scanner scanner = new Scanner(System.in); System.out.println("请输入聊天内容: "); String message = scanner.nextLine(); // 输出消息到ChatServer printStream.println(message); printStream.flush(); } catch (IOException e) { throw new RuntimeException(e); } } } }
7 创建客户端Client用于接收消息的线程类ReadThread
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.Socket; public class ReadThread extends Thread { private final Socket socket; public ReadThread(Socket socket) { this.socket = socket; } @Override public void run() { while (true) { try { // 从ChatServer获取消息 InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String message = bufferedReader.readLine(); System.out.println(message); } catch (IOException e) { throw new RuntimeException(e); } } } }
项目结构如下图
8 测试
先运行LoginServer和ChatServer,再运行多个Client
设置IDEA允许运行多个实例
8.1 登录
8.2 群聊
8.3 单聊
加载全部内容