基于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();
}
}
}
执行效果