「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
业务逻辑分析
(1):多个客户端连接到服务端
(2):一个客户端发送消息,其它客户端都能接收到这条消息
(3):用户退出群聊
上代码:服务端
Server.class
public class Server{
private int DEFAULT_PORT = 80;
//当用户发送 quit 的时候代表该客户端要退出群聊
private String QUIT = "quit";
private ServerSocket serverSocket;
//用来存储每一个客户端
private Map<Integer,Writer> connectedClients;
public Server() {
connectedClients = new HashMap<Integer,Writer>();
}
//有新客户端连接
public void addClient(Socket socket) throws IOException {
if(socket != null) {
int port = socket.getPort();
BufferWriter writer = new BufferWriter(new OutputStreamWriter(scoket.getOutputStream()));
connectedClients.put(port,writer);
System.out.println("客户端[" + port +"] 已经连接到服务器");
}
}
//客户端下线
public void removeClient(Socket socket) throws IOException {
if(socket != null && connectedClients.containsKey(socket.getPort())) {
int port = socket.getPort();
Writer writer = connectedClients.get(port);
writer.close();
connectedClients.remove(port);
System.out.println("客户端[" + port +"] 已经连接下线");
}
}
//判断客户端是否准备下线
public boolean readyToQuit(String msg) {
return QUIT.equals(msg);
}
//群发消息
public void sendMsg(String msg, Socket socket) {
int port = socket.getPort();
for(Integer id : connectedClients.keySet()) {
if(!port.equals(id)) {
Writer writer = connectedClients.get(id);
writer.writer(msg + "\n");
writer.flush();
}
}
}
//启动入口
public void start() {
try{
serverSocket = new ServerSocket(DEFAULT_PORT);
System.out.println("服务器已经启动..........");
while(true) {
Socket socket = serverSocket.accept();
//创建一个新的线程来处理客户端请求
new Thread(new ServerHandler(this,socket)).start();
}
}catch(Exception e) {
}finally {
if(serverSocket != null) {
try{
serverSocket.close();
}catch(Exception e){
}
}
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
}
ServerHandler.class
public class ServerHandler implements Runnable{
private Server server;
private Socket socket;
public ServerHandler(Server server, Socket socket) {
this.server = server;
this.socket = socket;
}
public void run() {
try{
//添加当前客户端到集合中去
server.addClient(socket);
//读取用户发送过来的消息,转发给其它用户
BufferReader reader = new BufferReader(new InputStreamReader(socket.getInputStream()));
String msg = null;
while((msg = reader.readLine()) != null) {
System.out.println("客户端【"+socket.getPort()+"】:" + msg);
//将消息转发给其它客户端
server.sendMsg(msg);
//检查用户是否下线
if(server.readyToQuit(msg)){
break;
}
}
}catch(Exception e) {
}finally{
System.out.println("客户端【"+socket.getPort()+"】已经下线");
try{
server.removeClient(socket);
}catch(Exception e) {}
}
}
}
客户端代码
CLient.class
public class Client {
private String DEFAULT_ADDRESS = "127.0.0.1";
private int DEFAULT_PORT = 80;
private Socket socket;
private BufferReader reader;
private BufferWriter writer;
private final String QUIT = "quit";
//发送消息给服务器
public void sendMsg(String msg,Socket socket) throws IOException{
if(!socket.isOutputShutdown()) {
writer.writer(msg + "\n");
writer.flush();
}
}
//从服务端接收消息
public String receiveMsg() throws IOException{
String msg = null;
if(!socket.isInputShutDown()) {
msg = reader.readLine();
}
return msg;
}
//检查用户是否退出
public boolean readyToQuit(String msg) {
return QUIT.equals(msg);
}
//关闭资源
public void close() {
if(writer != null) {
try{
writer.close();
}catch(Exception e) {
}
}
}
//启动入口
public void start() {
try{
socket = new Socket(DEFAULT_ADDRESS,DEFAULT_PORT);
//创建IO流
reader = new BufferReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferWriter(new OutputStreamWriter(socket.getOutputStream()));
//处理用户的输入
new Thread(new ClientHandle(this)).start();
//读取服务端转发的消息
String msg = null;
if((msg = receiveMsg()) != null) {
System.out.println(msg);
}
}catch(Exception e) {
}finally{
close();
}
}
public static void main(String[] args) {
Client client = new Client();
client.start();
}
}
ClientHandle.class
public class ClientHandle implements Runnable {
private Client client;
public ClientHandle(Client client) {
this.client = client;
}
public void run() {
try{
BufferReader input = new BufferReader(new InputStreamReader(System.in));
while(true) {
String input = input.readLine();
//向服务器发送消息
client.sendMsg(input);
//检查用户是否退出
if(client.readyToQuit(input)) {
break;
}
}
}catch(Exception e) {
}
}
}
测试
1:启动服务端
2:启动二个客户端
3:在客户端的控制台输入消息,然后回车查看效果