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端口,等待客户端连接,客户端连接成功后,保持该连接的通信
* @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();
}
}