Java Socket实现聊天室功能

2022-09-03 15:49:45 67 0
魁首哥

本文实例为大家分享了Java Socket实现聊天室的具体代码,供大家参考,具体内容如下

1 创建登录判断类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&lJkIjst;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.bpythonio.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.getOutputSjavascripttream();
      PrintStream printStream = new PrinphptStream(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 单聊

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

收藏
分享
海报
0 条评论
67
上一篇:Java数据结构之红黑树的原理及实现 下一篇:Spring AOP实现记录操作日志

本站已关闭游客评论,请登录或者注册后再评论吧~

忘记密码?

图形验证码