用Java从0开始实现Socket编程视频直播通信04—————界面以及登陆功能实现

有了前面的基础下,我们现在需要写一个界面,把客户端的界面用java.awt和java.swing写出来,设置一下基本参数和布局

import javax.swing.*;
import java.awt.*;

public class LoginUI {
    public void showUI(){
        // 创建一个窗口对象
        JFrame jf = new JFrame();
        jf.setSize(430, 550);  // 设置窗口大小
        jf.setTitle("登录界面");  // 设置窗口标题
        jf.setLocationRelativeTo(null);  // 将窗口居中显示
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  // 点击关闭按钮时退出程序

        // 设置窗口的布局管理器为流式布局
        FlowLayout flow = new FlowLayout();
        jf.setLayout(flow);

        // 加载并添加图片到窗口
        ImageIcon image = new ImageIcon("C:\\Users\\eugene\\Desktop\\1723363954729.png");
        JLabel jla = new JLabel(image);
        jf.add(jla);

        // 创建并添加账号标签
        JLabel user = new JLabel("账号:");
        jf.add(user);

        // 创建并设置账号文本框的尺寸,并添加到窗口
        JTextField usernameField = new JTextField();
        Dimension dm = new Dimension(350, 30);  // 设置文本框的尺寸
        usernameField.setPreferredSize(dm);  // 应用尺寸设置
        jf.add(usernameField);

        // 创建并添加密码标签
        JLabel pas = new JLabel("密码:");
        jf.add(pas);

        // 创建并设置密码文本框的尺寸,并添加到窗口
        JTextField passwordField = new JTextField();
        passwordField.setPreferredSize(dm);
        jf.add(passwordField);

        // 创建并添加登录按钮
        JButton loginBtn = new JButton("登录");
        jf.add(loginBtn);

        // 创建并添加注册按钮
        JButton registerBtn = new JButton("注册");
        jf.add(registerBtn);

        // 设置窗口为可见
        jf.setVisible(true);
    }

    public static void main(String[] args) {
        // 创建LoginUI对象并调用showUI方法显示登录界面
        LoginUI loginUI = new LoginUI();
        loginUI.showUI();
    }
}

图片的地址是自己的,可以自由更换

运行后可以得到简单的一个窗口,有聊天框还有按钮

这将做为客户端的界面

然后,我们先解决登录的问题,这需要读取文本框里的内容,并建立一个保存账号密码的数组与之进行比对,然后将结果输出

package com.clclient0809;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class LoginUI {
    public static void main(String[] args) {
        // 创建MClient对象
        MClient mClient = new MClient();
        // 创建UserManage对象,并将mClient对象传递进去
        UserManage userManage = new UserManage(mClient);
        // 创建并显示登录界面
        new LoginUI(userManage).showUI();
    }

    private UserManage userManage;

    // 构造方法,接收一个UserManage对象并将其赋值给成员变量userManage
    public LoginUI(UserManage userManage){
        this.userManage = userManage;
    }

    public void showUI() {
        // 创建窗口对象
        JFrame jf = new JFrame();
        // 设置窗口的大小(宽430,高550)
        jf.setSize(430, 550);
        // 设置窗口标题为“登录界面”
        jf.setTitle("登录界面");
        // 将窗口居中显示
        jf.setLocationRelativeTo(null);
        // 设置默认关闭操作,退出程序
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // 设置窗口的布局管理器为流式布局
        FlowLayout flow = new FlowLayout();
        jf.setLayout(flow);

        // 加载图片并添加到窗口的标签中
        ImageIcon image = new ImageIcon("C:\\Users\\eugene\\Desktop\\1723364705862.png");
        JLabel jla = new JLabel(image);
        jf.add(jla);

        // 创建并添加“账号”标签
        JLabel user = new JLabel("账号:");
        jf.add(user);

        // 创建并设置账号文本框的尺寸,并添加到窗口
        JTextField usernameField = new JTextField();
        Dimension dm = new Dimension(350, 30);  // 设置文本框的尺寸
        usernameField.setPreferredSize(dm);  // 应用尺寸设置
        jf.add(usernameField);

        // 创建并添加“密码”标签
        JLabel pas = new JLabel("密码:");
        jf.add(pas);

        // 创建并设置密码文本框的尺寸,并添加到窗口
        JTextField passwordField = new JTextField();
        passwordField.setPreferredSize(dm);
        jf.add(passwordField);

        // 创建并添加登录按钮
        JButton loginBtn = new JButton("登录");
        jf.add(loginBtn);

        // 创建并添加注册按钮
        JButton registerBtn = new JButton("注册");
        jf.add(registerBtn);

        // 为登录按钮添加点击事件监听器(匿名内部类实现)
        loginBtn.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                // 按钮被点击时输出信息
                System.out.println("按钮启动了");
                // 获取输入的账号和密码
                String username = usernameField.getText();
                String password = passwordField.getText();

                // 调用userManage对象的login方法进行验证
                if(userManage.login(username,password)){
                    System.out.println("登录成功...");
                }else{
                    System.out.println("登录失败...");
                }
            }
        });

        // 设置窗口为可见,确保所有组件在设置可见之前已被添加到窗口中
        jf.setVisible(true);
    }
}

同时为了保持一致性,我们把一些静态的值写在一个接口里,这样的接口应该在服务端和客户端都要写一个

package comserver240808;

public interface MsgType {
    //登录
    public static final String LOGIN = "login";

    //注册
    public static final String REGISTER = "REGISTER";

    public static final String SUCCESS = "SUCCESS";
    public static final String ERROR = "ERROR";

}

重写了按键点击后的内容,这里我是新写了一个类,调用里面的方法进行判断 

package com.clclient0809;

public class UserManage implements MsgType{
    private MClient mClient;

    public UserManage( MClient mClient){
        this.mClient = mClient;
    }
    //登录
    public boolean login(String username,String password){
        //发送账号,密码
        mClient.sendMessage(LOGIN+":"+username+":"+password);
        System.out.println("发送账号密码");
        //读取服务端结果
        String response = mClient.readMsg();
        System.out.println("读取服务端的结果");
        if(SUCCESS.equals(response)){
            return true;
        }
        return false;
    }


}

它将文字框的信息处理为LOGIN+":"+username+":"+password的形式发送给服务端并且读取返回的结果,最后以boolean的形式返回

为了保存和检索用户,我们单独建立一个User类

package comserver240808;

public class User {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

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

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

    }


}

在改进一下服务端,加入一些默认的好友用于测试,同时因为收发消息的功能应该位于登录之后,将其删除,并将这些数据传给线程

package comserver240808;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MServer {
    //自定义服务器
    public void creatServer() throws Exception{
        //创建服务器
        ServerSocket  server = new ServerSocket(8899);
        System.out.println("启动服务器。。。");
        //保存所有上线好友
        Map<User,Socket> map = new HashMap<>();
        //默认注册好友
        List<User> userList = new ArrayList<>();
        for(int i=1;i<=5;i++){
            userList.add(new User(i+"0",i+"0"));
        }
        while (true) {
            //阻塞监听连接过来的客户端
            Socket socket = server.accept();
            //启动线程跟客户端通信
            ServerThread st = new ServerThread(socket,map,userList);
            new Thread(st).start();
        }

    }

    public static void main(String[] args) {
        try {
            new MServer().creatServer();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

最后,将判断账号密码是否正确的方法加在线程里

package comserver240808;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.List;
import java.util.Map;

// 负责与客户端通信的线程
public class ServerThread implements Runnable, MsgType {
    private Socket socket;
    private InputStream inputStream;
    private OutputStream outputStream;
    private Map<User, Socket> map; // 已上线的好友
    private Server server;
    private List<User> userList; // 已注册的好友列表

    // 构造方法,初始化socket、map、userList,并创建Server对象
    public ServerThread(Socket socket, Map<User, Socket> map, List<User> userList) {
        this.socket = socket;
        this.map = map;
        this.userList = userList;
        server = new Server(socket);
    }

    // 线程的run方法,持续监听和处理客户端消息
    @Override
    public void run() {
        while (true) {
            try {
                // 读取客户端发送的消息
                String msg = server.readMsg();
                System.out.println("msg :" + msg);

                // 根据分隔符“:”分割消息,得到消息类型和内容
                String[] msgArr = msg.split(":");
                switch (msgArr[0]) {
                    case LOGIN: // 处理登录请求
                        handleLogin(msgArr[1], msgArr[2]);
                        System.out.println("msgArr[1],msgArr[2]" + msgArr[1] + msgArr[2]);
                        break;
                    case REGISTER: // 处理注册请求
                        // 注册的处理逻辑可以在这里实现
                        break;
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    // 处理登录逻辑
    private void handleLogin(String username, String password) {
        for (User user : userList) {
            // 检查用户名和密码是否匹配
            if (user.getUsername().equals(username) && user.getPassword().equals(password)) {
                // 如果匹配,发送登录成功的消息
                server.sendMessage(SUCCESS);
                return;
            }
        }
        // 如果所有用户都不匹配,发送登录失败的消息
        server.sendMessage(ERROR);
    }

    // 从客户端读取数据
    public String readMsg(InputStream inputStream) throws Exception {
        StringBuilder stringBuilder = new StringBuilder();
        int b = 0;
        // 读取输入流中的数据,直到遇到回车符(13)为止
        while ((b = inputStream.read()) != 13) {
            // 将读取到的字符拼接成一条完整的消息
            stringBuilder.append((char) b);
        }
        // 返回去掉首尾空白字符的消息字符串
        return stringBuilder.toString().trim();
    }
}

最后验证一下结果

10 10 是默认的用户,看到状态栏显示登录成功

11 11 不存在这样的用户,识别出来不匹配,状态栏显示登陆失败

至此我们实现了登录的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值