TCP服务器和客户端学生管理系统(第二天)完整版
一,工具类(util包中)
1.1 客户端用户操作枚举
package com.qfedu.student.system.client.util;
/**
* @author Anonymous 2020/3/18 11:39
*/
public enum ClientOperation {
/**
* 用户操作枚举
*/
FIND_ALL(1, "findAll"),
FIND_ONE(2, "findOne"),
ADD(3, "addStudent"),
MODIFY(4, "modifyStudent"),
REMOVE(5, "removeStudent"),
SORT_STU(6, "sortStu"),
FILTER_STU(7, "filterStu"),
LOGOUT(8, "logout");
private int id;
private String methodName;
ClientOperation() {
}
ClientOperation(int id, String methodName) {
this.id = id;
this.methodName = methodName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
}
1.2 服务端排序方法工具类
package com.qfedu.student.system.server.util;
import com.qfedu.student.system.server.entity.Student;
/**
* @author Anonymous 2020/3/18 16:05
*/
public class SortMethodUtil {
public static int ageAsc(Student stu1, Student stu2) {
return stu1.getAge() - stu2.getAge();
}
public static int ageDesc(Student stu1, Student stu2) {
return stu2.getAge() - stu1.getAge();
}
public static int mathScoreAsc(Student stu1, Student stu2) {
return stu1.getMathScore() - stu2.getMathScore();
}
public static int mathScoreDesc(Student stu1, Student stu2) {
return stu2.getMathScore() - stu1.getMathScore();
}
public static int chnScoreAsc(Student stu1, Student stu2) {
return stu1.getChnScore() - stu2.getChnScore();
}
public static int chnScoreDesc(Student stu1, Student stu2) {
return stu2.getChnScore() - stu1.getChnScore();
}
public static int engScoreAsc(Student stu1, Student stu2) {
return stu1.getEngScore() - stu2.getEngScore();
}
public static int engScoreDesc(Student stu1, Student stu2) {
return stu2.getEngScore() - stu1.getEngScore();
}
public static int totalScoreAsc(Student stu1, Student stu2) {
return stu1.getTotalScore() - stu2.getTotalScore();
}
public static int totalScoreDesc(Student stu1, Student stu2) {
return stu2.getTotalScore() - stu1.getTotalScore();
}
}
二,服务端
2.1 服务器数据处理中转站(controller包中)
package com.qfedu.student.system.server.controller;
import com.qfedu.student.system.server.service.StudentService;
import com.qfedu.student.system.server.tcp.ServerTcp;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.channels.SelectionKey;
/**
* 服务器数据处理中转站
*
* @author Anonymous 2020/3/18 15:04
*/
public class ServerController {
private static StudentService service = new StudentService();
/**
* 处理客户端发送数据,调用执行StudentDao层方法
*
* @param server ServerTcp服务器对象
* @param key SelectionKey 对应当前客户端发送数据SocketChannel
* @param message 客户端发送的请求
*/
public static void processingData(ServerTcp server,SelectionKey key, String message)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<StudentService> cls = StudentService.class;
String sendMsg = null;
// addStu:JsonString
String methodName = message.substring(0, message.indexOf(":"));
message = message.substring(message.indexOf(":") + 1);
// 执行close方法
if ("close".equals(methodName)) {
Method method = cls.getMethod(methodName, SelectionKey.class);
method.invoke(service, key);
// 终止当前方法
return;
} else if ("findAll".equals(methodName)) {
// 执行findAll方法
Method method = cls.getMethod(methodName);
sendMsg = (String) method.invoke(service);
} else {
// 执行其他功能方法
Method method = cls.getMethod(methodName, String.class);
sendMsg = (String) method.invoke(service, message);
}
server.sendMessage(key, sendMsg);
}
}
2.2 服务层(service包中)
package com.qfedu.student.system.server.service;
import com.qfedu.student.system.server.dao.StudentDao;
import com.qfedu.student.system.server.entity.Student;
import com.qfedu.student.system.server.util.JsonUtil;
import com.qfedu.student.system.server.util.SortMethodUtil;
import java.lang.reflect.Method;
import java.nio.channels.SelectionKey;
import java.util.ArrayList;
import java.util.List;
/**
* StudentService服务层
*
* @author Anonymous 2020/3/18 15:14
*/
public class StudentService {
/**
* StudentService保存一个计数器,一会儿保存到文件中
*/
private static int count = 1;
static {
// 读取文件,修改count
}
/**
* StudentDao层,数据控制层
*/
private StudentDao dao = StudentDao.getInstance();
private final static String OP_SUCCESS = "操作成功";
private final static String OP_FAILED = "操作失败";
private final static String NOT_FOUND = "查无此人";
private final static String EMPTY_SET = "无数据";
/**
* 登陆验证方法
*
* @param message 带有用户名和密码的字符串
* @return 登陆验证消息
*/
public String login(String message) {
String[] split = message.split(":");
if ("骚磊".equals(split[0]) && "123456".equals(split[1])) {
return "success";
} else {
return "failed";
}
}
/**
* 添加学生的方法
*
* @param message 客户端发送过来的带有学生信息的Json格式字符串
* @return 添加状态信息
*/
public String addStu(String message) {
Student student = JsonUtil.jsonToStudent(message);
student.setId(count++);
boolean ret = dao.add(student);
return ret ? OP_SUCCESS : OP_FAILED;
}
/**
* 删除学生的方法
*
* @param message 需要删除学生的ID信息字符串
* @return 操作状态
*/
public String deleteStu(String message) {
int id = Integer.parseInt(message);
Student remove = dao.remove(id);
return remove != null ? OP_SUCCESS : OP_FAILED;
}
/**
* 修改指定学生信息方法
*
* @param message 客户端发送的需要修改信息对应Student Json格式字符串
* @return 操作状态
*/
public String modifyStu(String message) {
Student student = JsonUtil.jsonToStudent(message);
Integer id = student.getId();
dao.modifyStudent(id, student);
return OP_SUCCESS;
}
/**
* 查询对应ID的学生
*
* @param message 指定学生ID信息字符串
* @return 找到对应学生,返回当前Student信息对应的Json格式字符串,没有找到返回NOT_FOUND
*/
public String findOne(String message) {
int id = Integer.parseInt(message);
Student student = dao.getStudentById(id);
return student != null ? JsonUtil.studentToJson(student) : NOT_FOUND;
}
/**
* 返回所有所有学生信息Json格式字符串
*
* @return 如果存在学生信息,返回Json格式字符串,没有返回EMPTY_SET
*/
public String findAll() {
ArrayList<Student> list = dao.getAllStudents();
return list.size() != 0 ? JsonUtil.studentListToJson(list) : EMPTY_SET;
}
/**
* 按照客户端指定的消息进行数据过程
*
* @param message 带有age消息要求的字符串 min,max 例如: 10,20
* @return 返回过滤之后的学生信息List集合对应Json各种字符串,如果没有数据发,返回EMPTY_SET
*/
public String filterStu(String message) {
String[] split = message.split(",");
int min = Integer.parseInt(split[0]);
int max = Integer.parseInt(split[1]);
List<Student> list = dao.filter(student -> student.getAge() >= min && student.getAge() <= max);
return list != null ? JsonUtil.studentListToJson(list) : EMPTY_SET;
}
@SuppressWarnings("all")
public String sortStu(String message) {
List<Student> list = null;
switch (message) {
// 方法引用 类名操作方法引用
case "1":
list = dao.sortUsingCompara(SortMethodUtil::ageAsc);
break;
case "2":
list = dao.sortUsingCompara(SortMethodUtil::ageDesc);
break;
case "3":
list = dao.sortUsingCompara(SortMethodUtil::mathScoreAsc);
break;
case "4":
list = dao.sortUsingCompara(SortMethodUtil::mathScoreDesc);
break;
case "5":
list = dao.sortUsingCompara(SortMethodUtil::chnScoreAsc);
break;
case "6":
list = dao.sortUsingCompara(SortMethodUtil::chnScoreDesc);
break;
case "7":
list = dao.sortUsingCompara(SortMethodUtil::engScoreAsc);
break;
case "8":
list = dao.sortUsingCompara(SortMethodUtil::engScoreDesc);
break;
case "9":
list = dao.sortUsingCompara(SortMethodUtil::totalScoreAsc);
break;
case "10":
list = dao.sortUsingCompara(SortMethodUtil::totalScoreDesc);
break;
default:
break;
}
return list.size() != 0 ? JsonUtil.studentListToJson(list) : EMPTY_SET;
}
/**
* 断开服务器和客户端连接
*
* @param key 需要关闭的对应客户端连接的SelectionKey
*/
public void close(SelectionKey key) {
key.cancel();
}
}
2.3 服务器TCP NIO连接客户端,注册客户端连接,发送消息,接收消息(tcp包中)
package com.qfedu.student.system.server.tcp;
import com.qfedu.student.system.server.controller.ServerController;
import com.qfedu.student.system.server.dao.StudentDao;
import com.qfedu.student.system.server.util.JsonUtil;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
/**
* 服务器TCP NIO连接客户端,注册客户端连接,发送消息,接收消息
*
* @author Anonymous 2020/3/17 14:33
*/
public class ServerTcp {
/**
* ServerSocketChannel对象,提供服务的核心
*/
private ServerSocketChannel serverSocket;
/**
* 选择器对象,需要注册到ServerSocketChannel
*/
private Selector selector;
/**
* 当前服务需要监听的端口号
*/
private static final int PORT = 8848;
/**
* ServerTcp构造方法,启动ServerSocketChannel服务
*/
public ServerTcp() {
try {
// 开启ServerSocket服务器
serverSocket = ServerSocketChannel.open();
// 开启选择器,大哥
selector = Selector.open();
// 绑定监听的端口
serverSocket.bind(new InetSocketAddress(PORT));
// 设置当前ServerSocketChannel为非阻塞IO
serverSocket.configureBlocking(false);
// 注册ServerSocketChannel,当前监听事件为SelectionKey.OP_ACCEPT
serverSocket.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 服务器核心方法,需要不断监听对应的端口,已经事件
*/
public void start() {
while (true) {
try {
// 保存监听连接状态
if (0 == selector.select(2000)) {
continue;
}
// 获取当前所有相应的selectKey
Set<SelectionKey> selectionKeys = selector.selectedKeys();
// 得到对应SelectionKey Set集合迭代器对象
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
// 请求连接状态
if (key.isAcceptable()) {
SocketChannel socket = serverSocket.accept();
socket.configureBlocking(false);
socket.register(selector, SelectionKey.OP_READ);
}
// socket发送数据到服务器
if (key.isReadable()) {
// 读取数据
receiveMessage(key);
}
iterator.remove();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 接收数据的方法,需要的参数是SelectionKey
*
* @param key 对应当前SelectionKey接收数据
*/
public void receiveMessage(SelectionKey key) {
SocketChannel channel = (SocketChannel) key.channel();
int length = -1;
ByteBuffer buffer = ByteBuffer.allocate(1024);
StringBuilder stb = new StringBuilder();
try {
while ((length = channel.read(buffer)) > 0) {
stb.append(new String(buffer.array(), 0, length));
}
} catch (IOException e) {
e.printStackTrace();
}
String s = stb.toString();
// 处理对应的功能,Controller
try {
ServerController.processingData(this, key, s);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 发送数据
*
* @param key 对应当前客户端请求的SelectionKey对象
* @param message 需要发送的字符串数据
*/
public void sendMessage(SelectionKey key, String message) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
try {
channel.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
StudentDao dao = StudentDao.getInstance();
JsonUtil.readDataFromJsonFile(dao);
Thread thread = new Thread(() -> {
try {
while (true) {
Thread.sleep(1000 * 5);
JsonUtil.saveDataToJsonFile(dao);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.setDaemon(true);
thread.start();
new ServerTcp().start();
}
}
三,客户端
3.1 客户端控制层 客户端功能 <> 数据交互 <> 服务器(controller包中)
package com.qfedu.student.system.client.controller;
import com.qfedu.student.system.client.service.ClientService;
import com.qfedu.student.system.client.tcp.ClientTcp;
/**
* 客户端控制层
* 客户端功能 <==> 数据交互 <==> 服务器
*
* @author Anonymous 2020/3/17 15:23
*/
public class ClientController {
/**
* 客户端服务层对象,提供客户端操作
*/
private ClientService service = new ClientService();
/**
* TCP服务器客户端连接对象
*/
private ClientTcp client = new ClientTcp();
/**
* 成功信息
*/
private static final String SUCCESS = "success";
/**
* 查无此人
*/
private static final String NOT_FOUND = "查无此人";
private final static String EMPTY_SET = "无数据";
/**
* 用户登陆方法,登陆成功,继续操作,登陆失败,关闭客户端,断开
* 服务器连接,销毁socket
*/
public void login() {
String s = service.loginMessage();
client.sendMessage("login:" + s);
String s1 = client.receiveMessage();
if (SUCCESS.equals(s1)) {
System.out.println("登陆成功");
} else {
System.out.println("登陆失败");
logout();
}
}
/**
* 客户端退出
*/
public void logout() {
// 断开连接
client.sendMessage("close:");
// 终止程序
System.exit(0);
}
/**
* 客户端Add方法
*/
public void addStudent() {
// 从客户端功能中呼气一个Student数据对应的JsonString
String studentJsonString = service.getStudent();
// 服务器执行的方法 addStudent方法 String
// 服务器端 addStudent(String jsonString)
// addStudent:{"age":16,"chnScore":100,"engScore":100,"gender":false,"id":1,"mathScore":100,"name":"骚磊","rank":1,"totalScore":300}
String message = "addStu:" + studentJsonString;
// 发送数据给服务器
client.sendMessage(message);
String s = client.receiveMessage();
System.out.println(s);
}
/**
* 删除指定ID学生操作
*/
public void removeStudent() {
// 获取指定删除的学生
Integer id = findOne();
// 是否确定删除
if (id != -1 && service.confirm()) {
client.sendMessage("deleteStu:" + id);
System.out.println(client.receiveMessage());
} else {
System.out.println("删除操作撤销");
}
}
/**
* 修改指定ID学生信息
*/
public void modifyStudent() {
Integer id = service.getStringId();
// 找到需要删除的学生
client.sendMessage("findOne:" + id);
String s = client.receiveMessage();
// 如果说没有找到,返回是字符串是"查无此人"
if (NOT_FOUND.equals(s)) {
System.out.println(s);
return;
}
String jsonString = service.modifyStudent(s);
client.sendMessage("modifyStu:" + jsonString);
String s1 = client.receiveMessage();
System.out.println(s1);
}
/**
* 展示一个学生信息
*
* @return 当前学生的ID号
*/
public Integer findOne() {
Integer id = service.getStringId();
// 找到需要删除的学生
client.sendMessage("findOne:" + id);
String s = client.receiveMessage();
// 如果说没有找到,返回是字符串是"查无此人"
if (NOT_FOUND.equals(s)) {
System.out.println(s);
return -1;
}
service.showStudent(s);
return id;
}
/**
* 展示所有学生信息
*/
public void findAll() {
client.sendMessage("findAll:");
String s = client.receiveMessage();
if (EMPTY_SET.equals(s)) {
System.out.println(s);
} else {
service.showStudentList(s);
}
}
/**
* 排序学生信息
*/
public void sortStu() {
Integer choose = service.sortChoose();
if (11 == choose) {
return;
}
client.sendMessage("sortStu:" + choose);
String s = client.receiveMessage();
if (EMPTY_SET.equals(s)) {
System.out.println(s);
} else {
service.showStudentList(s);
}
}
/**
* 过滤学生信息
*/
public void filterStu() {
String s = service.ageFilter();
client.sendMessage("filterStu:" + s);
String s1 = client.receiveMessage();
if (EMPTY_SET.equals(s)) {
System.out.println(s);
} else {
service.showStudentList(s1);
}
}
}
3.2 客户端主程序(mainproject包中)
package com.qfedu.student.system.client.mainproject;
import com.qfedu.student.system.client.controller.ClientController;
import com.qfedu.student.system.client.util.ClientOperation;
import java.lang.reflect.InvocationTargetException;
import java.util.Scanner;
/**
* 客户端主程序
*
* @author Anonymous 2020/3/18 11:17
*/
@SuppressWarnings("all")
public class ClientMain {
private static Scanner sc = new Scanner(System.in);
public static void main(String[] args)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
/* 核心控制层 */
ClientController controller = new ClientController();
/* 控制层Class对象 */
Class<ClientController> cls = ClientController.class;
/* 登陆 */
controller.login();
int choose = 0;
while (true) {
System.out.println("用户您好,骚磊学生系统");
System.out.println("1. 查看所有学生");
System.out.println("2. 查看指定学生");
System.out.println("3. 增加学生信息");
System.out.println("4. 修改指定学生");
System.out.println("5. 删除指定学生");
System.out.println("6. 指定信息排序");
System.out.println("7. 指定信息筛选");
System.out.println("8. 退出");
choose = sc.nextInt();
// 获取一个枚举类型数组
ClientOperation[] values = ClientOperation.values();
// 遍历枚举类型数组
for (ClientOperation value : values) {
// 找到对应枚举类型中的id和choose一致
if (choose == value.getId()) {
// 使用反射指定对应的方法
cls.getMethod(value.getMethodName()).invoke(controller);
break;
}
}
}
}
}
3.3 客户端可以执行的操作(service包中)
package com.qfedu.student.system.client.service;
import com.qfedu.student.system.client.entity.Student;
import com.qfedu.student.system.client.util.JsonUtil;
import java.util.List;
import java.util.Scanner;
/**
* 客户端可以执行的操作
*
* @author Anonymous 2020/3/17 15:55
*/
public class ClientService {
private static Scanner sc = new Scanner(System.in);
/**
* 添加学生信息,到服务器
*
* @return Student数据对应的Json格式字符串
*/
public String getStudent() {
sc.next();
System.out.println("请输入学生的姓名:");
String name = sc.next();
System.out.println("请输入学生的年龄:");
Integer age = sc.nextInt();
sc.next();
System.out.println("请输入学生的性别 男 或者 女:");
Boolean gender = sc.next().charAt(0) != '男';
System.out.println("请输入学生的语文成绩:");
Integer chnScore = sc.nextInt();
System.out.println("请输入学生的数学成绩:");
Integer mathScore = sc.nextInt();
System.out.println("请输入学生的英语成绩:");
Integer engScore = sc.nextInt();
Integer totalScore = chnScore + mathScore + engScore;
Student student = new Student(0, name, gender, age, mathScore, chnScore, engScore, totalScore, 0);
return JsonUtil.studentToJson(student);
}
/**
* 展示Json格式数据对应的保存Student数据List集合,
* 可以用到展示所有学生,排序结果,过滤数据结果
*
* @param jsonString 包含所有学生数据的Json格式字符串
*/
public void showStudentList(String jsonString) {
List<Student> students = JsonUtil.jsonToStudentList(jsonString);
for (Student student : students) {
System.out.println(student);
}
}
/**
* 展示指定学生信息
*
* @param jsonString Json格式字符串
*/
public void showStudent(String jsonString) {
Student student = JsonUtil.jsonToStudent(jsonString);
System.out.println(student);
}
/**
* 修改指定学生信息
*
* @param jsonString 对应Json格式字符串
* @return 修改之后的学生信息Json格式字符串
*/
public String modifyStudent(String jsonString) {
// 转换成对应的Student类型
Student student = JsonUtil.jsonToStudent(jsonString);
int choose = 0;
boolean flag = false;
while (true) {
System.out.println("ID: " + student.getId() + " Name: " + student.getName());
System.out.println("Age: " + student.getAge() + " Gender: " + (student.getGender() ? "女" : "男"));
System.out.println("chnScore: " + student.getChnScore() + " mathScore: " + student.getMathScore());
System.out.println("engScore: " + student.getEngScore() + " TotalScore: " + student.getTotalScore());
System.out.println("Rank: " + student.getRank());
System.out.println("1. 修改学生姓名:");
System.out.println("2. 修改学生年龄:");
System.out.println("3. 修改学生性别:");
System.out.println("4. 修改学生语文成绩:");
System.out.println("5. 修改学生数学成绩:");
System.out.println("6. 修改学生英语成绩:");
System.out.println("7. 退出");
choose = sc.nextInt();
sc.next();
switch (choose) {
case 1:
System.out.println("请输入学生的名字:");
String name = sc.next();
student.setName(name);
break;
case 2:
System.out.println("请输入学生的年龄:");
Integer age = sc.nextInt();
student.setAge(age);
break;
case 3:
System.out.println("请输入学生的性别 男 或者 女:");
Boolean gender = sc.next().charAt(0) != '男';
student.setGender(gender);
break;
case 4:
System.out.println("请输入学生的语文成绩:");
Integer chnScore = sc.nextInt();
// 修改总分,获取原总分 + 当前语文成绩 - 原语文成绩
student.setTotalScore(student.getTotalScore() + chnScore - student.getChnScore());
student.setChnScore(chnScore);
break;
case 5:
System.out.println("请输入学生的数学成绩:");
Integer mathScore = sc.nextInt();
student.setTotalScore(student.getTotalScore() + mathScore - student.getMathScore());
student.setMathScore(mathScore);
break;
case 6:
System.out.println("请输入学生的英语成绩:");
Integer engScore = sc.nextInt();
student.setTotalScore(student.getTotalScore() + engScore - student.getEngScore());
student.setEngScore(engScore);
break;
case 7:
flag = true;
break;
default:
System.out.println("选择错误");
break;
}
// 退出标记
if (flag) {
// 退出while true循环
break;
}
}
// 讲修改之后的Student信息,转换成一个Json格式字符串返回
return JsonUtil.studentToJson(student);
}
/**
* 获取用户指定操作的ID号,可以用于查询,修改,删除操作
*
* @return 用户指定的学生id号
*/
public Integer getStringId() {
System.out.println("请输入学生的ID号:");
return sc.nextInt();
}
/**
* 是否继续操作的确定弹框
*
* @return 返回用户确定操作的消息
*/
public boolean confirm() {
System.out.println("确认当前操作吗? Y or N");
return "Y".equalsIgnoreCase(sc.next());
}
/**
* 用户排序选择操作
*
* @return 用户排序选择
*/
public Integer sortChoose() {
System.out.println("1. 年龄升序");
System.out.println("2. 年龄降序");
System.out.println("3. 数学成绩降序");
System.out.println("4. 数学成绩升序");
System.out.println("5. 语文成绩降序");
System.out.println("6. 语文成绩升序");
System.out.println("7. 英语成绩降序");
System.out.println("8. 英语成绩升序");
System.out.println("9. 总成绩降序");
System.out.println("10. 总成绩升序");
System.out.println("11. 排序取消");
int choose = sc.nextInt();
return Math.min(choose, 11);
}
/**
* 用户返回过滤展示数据条件字符串
*
* @return 用户返回的过滤条件字符串
*/
public String ageFilter() {
System.out.println("请输入需要展示年龄的范围 最小值和最大值");
int min = sc.nextInt();
int max = sc.nextInt();
// XXX, XXX
if (min > max) {
return max +"," + min;
} else {
return min +"," + max;
}
}
/**
* 返回用户登陆的有效信息
*
* @return 用户登陆信息
*/
public String loginMessage() {
System.out.println("欢迎来到骚磊学生系统:");
System.out.println("请输入用户名:");
String userName = sc.next();
System.out.println("请输入密码:");
String password = sc.next();
return userName + ":" + password;
}
}
3.4 使用NIO完成客户端服务器连接,数据接收,数据发送过程(tcp包中)
package com.qfedu.student.system.client.tcp;
import com.qfedu.student.system.client.util.CloseUtil;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
/**
* 使用NIO完成客户端服务器连接,数据接收,数据发送过程
*
* @author Anonymous 2020/3/18 09:41
*/
public class ClientTcp {
/**
* NIO Socket客户端
*/
private SocketChannel socket = null;
/**
* 服务器IP地址
*/
private static String host = "192.168.31.154";
/**
* 服务器对应当前服务器的端口号
*/
private static int port = 8848;
/**
* ClientTcp构造方法,这里需要连接服务器得到TCP协议的客户端SocketChannel对象
*/
public ClientTcp() {
try {
// 1. 开启SocketChannel NIO服务器
socket = SocketChannel.open();
// 2. 设置当前NIO方式为非阻塞方式
socket.configureBlocking(false);
// 3. 确定连接主机IP地址和端口号学习的InetSocketAddress
InetSocketAddress address = new InetSocketAddress(host, port);
// 4. 连接服务器
if (!socket.connect(address)) {
while (!socket.finishConnect()) {
Thread.sleep(2000);
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
/**
* 从服务器接收数据
*
* @return 从服务器接收到的数据
*/
public String receiveMessage() {
int length = -1;
String str = null;
// 存在可能性 1024不够用!!!
ByteBuffer buffer = ByteBuffer.allocate(1024);
try {
StringBuilder stb = new StringBuilder();
while ((length = socket.read(buffer)) == 0) {}
stb.append(new String(buffer.array(), 0, length));
while ((length = socket.read(buffer)) > 0) {
stb.append(new String(buffer.array(), 0, length));
}
str = stb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
/**
* 发送数据给服务器,如果发送的数据是 "close:" 标记
*
* @param message 需要发送的数据
*/
public void sendMessage(String message) {
ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
try {
socket.write(buffer);
} catch (IOException e) {
e.printStackTrace();
} finally {
if ("close:".equals(message)) {
// 关闭客户端Socket
CloseUtil.closeAll(socket);
}
}
}
}
四,包名布局截图
4.1 服务端截图
客户端截图