Java-多用户即时通信系统-用户登录(服务器端)

本文介绍了使用Java构建的多用户即时通信系统中,服务器端如何实现用户登录功能,涉及User、Message和MessageType实体类,以及ServerSocket和线程的使用。

Java-多用户即时通信系统-用户登录(服务器端)

  • 根据前面的需求分析,实现服务器端用户登录功能;

1 实体类(放在common包下)

  • 也包括用户类(User)、消息类(Message)、消息类型接口(MessageType)

User

  • 用户类
/**
 * @author: SEA
 * @date: 2023/5/4
 */
public class User implements Serializable {
    private static final long serialVersionUID = 1L;//序列化ID,用来保证序列化和反序列化过程中,User类的一致性
    private String userID;//用户名
    private String password;//密码
    public User() {
    }

    public User(String userID, String password) {
        this.userID = userID;
        this.password = password;
    }

    public String getuserID() {
        return userID;
    }

    public void setuserID(String userID) {
        this.userID = userID;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "userID='" + userID + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

Message

  • 消息类
/**
 * @author: SEA
 * @date: 2023/5/4
 */
public class Message implements Serializable {
    private static final long serialVersionUID = 1L;//序列化ID,用来保证序列化和反序列化过程中,User类的一致性
    private String sender_ip;//发送方ip
    private String receiver_ip;//接收方ip
    private String send_data;//发送内容
    private String send_time;//发送时间
    private String message_type;//消息类型(如:文本,图片,音频,视频等)

    public Message() {
    }

    public Message(String sender_ip, String receiver_ip, String send_data, String send_time, String message_type) {
        this.sender_ip = sender_ip;
        this.receiver_ip = receiver_ip;
        this.send_data = send_data;
        this.send_time = send_time;
        this.message_type = message_type;
    }

    public String getSender_ip() {
        return sender_ip;
    }

    public void setSender_ip(String sender_ip) {
        this.sender_ip = sender_ip;
    }

    public String getReceiver_ip() {
        return receiver_ip;
    }

    public void setReceiver_ip(String receiver_ip) {
        this.receiver_ip = receiver_ip;
    }

    public String getSend_data() {
        return send_data;
    }

    public void setSend_data(String send_data) {
        this.send_data = send_data;
    }

    public String getSend_time() {
        return send_time;
    }

    public void setSend_time(String send_time) {
        this.send_time = send_time;
    }

    public String getMessage_type() {
        return message_type;
    }

    public void setMessage_type(String message_type) {
        this.message_type = message_type;
    }

    @Override
    public String toString() {
        return "Message{" +
                "sender_ip='" + sender_ip + '\'' +
                ", receiver_ip='" + receiver_ip + '\'' +
                ", send_data='" + send_data + '\'' +
                ", send_time='" + send_time + '\'' +
                ", message_type='" + message_type + '\'' +
                '}';
    }
}

MessageType

  • 消息类型接口
/**
 * @author: sea-365
 * @date: 2023/5/4 20:54
 */
public interface MessageType {
    String MESSAGE_LOGIN_SUCCEED = "1";//表示登录成功
    String MESSAGE_LOGIN_FAILED = "0";//表示登录成功
}

2 功能类(放在service包下)

QQServer

  • QQ服务器端,监听9999端口;
/**
 * QQ服务器端,监听9999端口,等待客户端连接,客户端连接成功后,保持该连接的通信
 * @author: sea-365
 * @date: 2023/5/5
 */
public class QQServer {
    public ServerSocket serverSocket = null;

    public QQServer(){
        try{
            //端口可以写在配置文件中,方便后续修改
            serverSocket = new ServerSocket(9999);
            System.out.println("监听9999端口,等待连接...");
            while(true) {
                //有客户端连接则获取到Socket对象,否则阻塞
                Socket socket = serverSocket.accept();
                ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                //获取客户端发送的User对象
                User user = (User) objectInputStream.readObject();
                //回复该客户端,是否登录成功
                Message message = new Message();
                //这里需要连接数据库进行验证,但是目前没有增加数据库这一块,暂时先假设只有一个用户(100,123456)可以登录成功
                if (user.getuserID().equals("100") && user.getPassword().equals("123456")) {//登录成功
                    System.out.println("客户端" + user.getuserID() + "登录成功!");
                    //返回登录成功message
                    message.setMessage_type(MessageType.MESSAGE_LOGIN_SUCCEED);
                    objectOutputStream.writeObject(message);

//                    socket.shutdownOutput();

                    //登录成功,创建一个线程,用于保持该连接的通信
                    ServerConnectClientThread serverConnectClientThread = new ServerConnectClientThread(socket, user.getuserID());
                    serverConnectClientThread.start();
                    //加入集合方便管理
                    ServerConnectClientThreadManage.addserverConnectClientThread(user.getuserID(), serverConnectClientThread);
                } else {//登录失败
                    System.out.println("登录失败,取消连接");
                    message.setMessage_type(MessageType.MESSAGE_LOGIN_FAILED);
                    objectOutputStream.writeObject(message);
                    socket.shutdownOutput();

                    objectOutputStream.close();
                    objectInputStream.close();
                    socket.close();
                }
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            try {
                serverSocket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }
}

ServerConnectClientThread

  • 用于保持服务器端与某一个客户端通信的线程类
/**
 * @author: sea-365
 * @date: 2023/5/5 20:48
 * 用于保持服务器端与某一个客户端通信的线程类
 */
public class ServerConnectClientThread extends Thread{
    private Socket socket;
    private String userID;//与某个用户(客户端)通信

    public ServerConnectClientThread() {
    }

    public ServerConnectClientThread(Socket socket, String userID) {
        this.socket = socket;
        this.userID = userID;
    }

    public Socket getSocket() {
        return socket;
    }

    public void setSocket(Socket socket) {
        this.socket = socket;
    }

    public String getUserID() {
        return userID;
    }

    public void setUserID(String userID) {
        this.userID = userID;
    }

    @Override
    public void run() {
        //与客户端一样,服务器端也需要不断接收客户端发送的数据,并且还可以向客户端发送数据
        while(true){
            try {
                System.out.println("与用户" + userID + "保持连接,正在读取数据...");
                ObjectInputStream objectInputStream = new ObjectInputStream(this.socket.getInputStream());
                Message message = (Message) objectInputStream.readObject();
                System.out.println(" 处理客户端发送的消息: " +message.getSend_data());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

ServerConnectClientThreadManage

  • 管理ServerConnectClientThread线程的类
/**
 * @author: sea-365
 * @date: 2023/5/5 20:59
 */
public class ServerConnectClientThreadManage {
    private static HashMap<String, ServerConnectClientThread> serverConnectClientThreads = new HashMap<>();

    public ServerConnectClientThreadManage() {
    }

    public static void addserverConnectClientThread(String userID, ServerConnectClientThread serverConnectClientThread){
        serverConnectClientThreads.put(userID, serverConnectClientThread);
    }

    public static ServerConnectClientThread getserverConnectClientThread(String userID){
        return serverConnectClientThreads.get(userID);
    }
}

3 框架类(放在frame包下)

QQFrame

  • 服务器端启动框架;
/**
 * @author: sea-365
 * @date: 2023/5/5 21:22
 */
public class QQFrame {
    public static void main(String[] args) {
        QQServer qqServer = new QQServer();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SEA-365

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值