(多线程、IO流、网络编程、properties集合)好玩的网络编程交互实现服务器端【ServerSocket】和客户端【Socket】的注册与登录功能

基于TCP的网络编程综合案例,结合了服务器端客户端的交互和数据传输思想


Socket编程:
Socket(套接字)是网络中的一个通信节点
分为客户端(Socket)与服务端(ServerSocket
通信要求: IP地址 + 端口号


开发步骤

  • 建立通信连接(会话):
    • 创建ServerSocket,指定端口号
    • 调用accept等待客户端接入
  • 客户端请求服务器:
    • 创建Socket,指定服务器IP + 端口号
    • 使用输出流,发送请求数据给服务器
    • 使用输入流,接收响应数据到客户端(等待)
  • 服务器响应客户端:
    • 使用输入流,接收请求数据到服务器(等待)
    • 使用输出流,发送响应数据给客户端

综合案例要求

  • 使用Scoket编程实现服务器端注册:
    • 注册信息保存在properties文件中
    • 封装格式自定义
    • 注册成功后返回字符串“注册成功!”
  • 使用Scoket编程实现服务器端登录:
    • 获取properties文件中的用户信息,进行用户名与密码的校验
    • 检验成功后返回字符串“登陆成功!”

方法摘要

位置 使用到的方法 解释
File类 public boolean exists() 测试此抽象路径名表示的文件或目录是否存在
java.util.Properties public void load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)
java.util.Map(接口) boolean containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true
java.util.Properties public Object setProperty(String key, String value) 将键值对存入集合Properties中
java.lang.String public String[] split(String regex) 将字符串根据regex做拆分

在这里插入图片描述


在这里插入图片描述


客户端操作菜单

import com.sweetown.sockets.comprehensivecase.client.Client;

import java.io.IOException;
import java.util.Scanner;

/**
 * @author Ziph
 * 菜单
 */
public class StartMenu {
    public static void main(String[] args) throws IOException, InterruptedException {
        Client client = new Client();
        System.out.println("----------聊天室系统----------");
        Scanner scanner = new Scanner(System.in);
        int choice;
        do {
            System.out.println("1.注册");
            System.out.println("2.登录");
            System.out.println("0.退出");
            System.out.println("请做出您的选择:");
            choice = scanner.nextInt();
            switch (choice) {
                case 1:
                    client.reg();
                    break;
                case 2:
                    client.login();
                default:
                    break;
            }
        } while (choice != 0);
        System.out.println("欢迎下次再来!");
    }
}

登录注册服务主线程

import com.sweetown.sockets.comprehensivecase.server.Server;

import java.io.IOException;

/**
 * @author Ziph
 * 两个线程启动注册、登录服务
 * 保证两个服务互不干扰,可以同时并发
 */
public class StartServer {
    public static void main(String[] args) {
        /**
         * 启动服务端
         * 使用两个线程启动服务,保证两个服务可以并发访问
         * 注意:两个服务线程使用了匿名内部类
         */
        Server server = new Server();
        new Thread() {
            @Override
            public void run() {
                /*1.服务器启动注册功能*/
                try {
                    server.registerUser();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                /*2.服务器启动登录功能*/
                try {
                    server.login();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
}

服务器端代码

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;

/**
 * @author Ziph
 * 服务器端:
 * 1.注册功能
 * 2.登录功能
 * 注意:
 * 1.注册和登录任务交给两个线程任务
 * 2.把客户端注册的用户名和密码存在userPros.properties文件中
 */
public class Server {
    /**
     * 存储用户信息的配置文件
     */
    private Properties userPros;

    public Server() {
        /*用于存储properties文件内容*/
        userPros = new Properties();
        File file = new File("Files\\userPros.properties");
        /*判断文件是否存在*/
        if (file.exists()) {
            try {
                /*把外部文件加载到userPros对象中*/
                userPros.load(new FileReader(file));
            } catch (IOException e) {
                System.out.println("文件加载失败");
            }
        }
    }

    /**
     * 注册功能
     */
    public void registerUser() throws IOException {
        /*1.创建服务器*/
        ServerSocket server = new ServerSocket(6666);
        System.out.println("注册线程已启动");
        while (true) {
            /*2.接收客户端*/
            Socket client = server.accept();
            /*3.将客户端对象和配置文件传给注册线程*/
            new RegThread(client, userPros).start();
        }
    }

    /**
     * 登录功能
     */
    public void login() throws IOException {
        ServerSocket server = new ServerSocket(7777);
        System.out.println("登录线程已启动");
        while (true) {
            Socket client = server.accept();
            LoginThread loginThread = new LoginThread(client, userPros);
            loginThread.start();
        }
    }
}
import java.io.*;
import java.net.Socket;
import java.util.Properties;

/**
 * @author Ziph
 * 服务器端注册功能的线程
 * 用来接收客户端传输的信息而做出反馈(注册)
 */
public class RegThread extends Thread {
    private Socket client;
    private Properties userPros;

    public RegThread(Socket client, Properties userPros) {
        this.client = client;
        this.userPros = userPros;
    }

    @Override
    public void run() {
        try {
            /*1.获得输入输出流*/
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
            PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"));
            /*2.获得用户提交的数据————例如:用户名#密码*/
            String userInfo = bufferedReader.readLine();
            String[] users = userInfo.split("#");
            String userName = users[0];
            String passWord = users[1];
            /*3.判断用户名是否存在*/
            if (userPros.containsKey(userName)) {
                printWriter.println("用户名已存在");
                printWriter.flush();
            } else {
                /*将对象存入集合*/
                userPros.setProperty(userName, passWord);
                /*存入硬盘的文件*/
                userPros.store(new FileWriter("Files\\userPros.properties"), null);
                printWriter.println("注册成功");
                printWriter.flush();
            }
            /*4.关闭资源*/
            printWriter.close();
            bufferedReader.close();
            client.close();
        } catch (IOException e) {
            e.getStackTrace();
        }
    }
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Properties;

/**
 * @author Ziph
 * 服务器端注册功能的线程
 * 用来接收客户端传输的信息而做出反馈(登录)
 */
public class LoginThread extends Thread {
    private Socket client;
    private Properties userPros;

    public LoginThread(Socket client, Properties userPros) {
        this.client = client;
        this.userPros = userPros;
    }

    @Override
    public void run() {
        try {
            /*1.获取输入输出流*/
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));

            PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"));

            /*2.接收客户端输入的用户名、密码*/
            String userInfo = bufferedReader.readLine();
            String[] users = userInfo.split("#");
            String userName = users[0];
            String passWord = users[1];

            /*3.用户名密码校验*/
            /*用户名已存在*/
            if (userPros.containsKey(userName)) {
                if (userPros.getProperty(userName).equals(passWord)) {
                    printWriter.println("登录成功");
                    printWriter.flush();
                } else {
                    printWriter.println("登录失败");
                    printWriter.flush();
                }
            } else {
                printWriter.println("登录失败,账号不存在");
                printWriter.flush();
            }
            /*4.关闭资源*/
            printWriter.close();
            bufferedReader.close();
            client.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

客户端代码

import java.io.IOException;
import java.net.Socket;

/**
 * @author Ziph
 * 客户端登录、注册服务入口
 */
public class Client {
    /**
     * 注册功能入口
     */
    public void reg() throws IOException, InterruptedException {
        /*1.连接服务器*/
        Socket client = new Socket("192.168.19.163", 6666);
        /*2.把客户端传给线程*/
        ClientRegThread clientRegThread = new ClientRegThread(client);
        /*3.启动线程*/
        clientRegThread.start();
        /*4.为了避免主线程先执行,调用join方法插队,让主线程进入等待*/
        clientRegThread.join();
    }

    /**
     * 登录 功能入口
     */
    public void login() throws IOException, InterruptedException {
        /*1.连接登录服务器*/
        Socket client = new Socket("192.168.19.163", 7777);
        /*2.客户端传给线程*/
        ClientLoginThread clientLoginThread = new ClientLoginThread(client);
        /*3.启动线程*/
        clientLoginThread.start();
        /*4.避免异步*/
        clientLoginThread.join();
    }
}
import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * @author Ziph
 * 客户端注册功能线程
 * 用来传输服务器端信息(注册信息)
 */
public class ClientRegThread extends Thread {
    private Socket client;

    public ClientRegThread(Socket client) {
        this.client = client;
    }

    @Override
    public void run() {
        try {
            /*1.获得输入输出流*/
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));

            PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"));

            /*2.用户输入信息并以指定文件形式保存在文件中*/
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入用户名:");
            String userName = scanner.next();
            System.out.println("请输入密码:");
            String passWord = scanner.next();
            String userInfo = userName + "#" + passWord;

            /*3.提交给服务器*/
            printWriter.println(userInfo);
            printWriter.flush();

            /*4.接受服务器的回应*/
            String message = bufferedReader.readLine();
            System.out.println(message);

            /*5.关闭资源*/
            printWriter.close();
            bufferedReader.close();
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * @author Ziph
 * 客户端登录功能线程
 * 用来传输服务器端信息(登录信息)
 */
public class ClientLoginThread extends Thread{
    private Socket client;

    public ClientLoginThread(Socket client) {
        this.client = client;
    }

    @Override
    public void run() {
        try {
            /*1.获得输入输出流*/
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));

            PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"));

            /*2.用户输入信息并以指定文件形式保存在文件中*/
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入用户名:");
            String userName = scanner.next();
            System.out.println("请输入密码:");
            String passWord = scanner.next();
            String userInfo = userName + "#" + passWord;

            /*3.提交给服务器*/
            printWriter.println(userInfo);
            printWriter.flush();

            /*4.接收响应结果*/
            String message = bufferedReader.readLine();
            System.out.println(message);

            /*5.关闭资源*/
            printWriter.close();
            bufferedReader.close();
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

执行效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了120 篇原创文章 · 获赞 181 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_44170221/article/details/104975727