2.编写客户端
接下来我们来定义客户端,在客户端中我们添加一组待发送的消息,随机给服务器端发送一个消息,实现代码如下:
/** * 客户端 */ class MySocketClient { public static void main(String[] args) throws IOException { // 启动 Socket 并尝试连接服务器 Socket socket = new Socket("127.0.0.1", 9093); // 发送消息合集(随机发送一条消息) final String[] message = {"Hi,Java.", "Hi,SQL~", "关注公众号|Java中文社群."}; // 创建协议封装对象 SocketPacket socketPacket = new SocketPacket(); try (OutputStream outputStream = socket.getOutputStream()) { // 给服务器端发送 10 次消息 for (int i = 0; i < 10; i++) { // 随机发送一条消息 String msg = message[new Random().nextInt(message.length)]; // 将内容封装为:协议头+协议体 byte[] bytes = socketPacket.toBytes(msg); // 发送消息 outputStream.write(bytes, 0, bytes.length); outputStream.flush(); } } } }
3.编写服务器端
服务器端我们使用线程池来处理每个客户端的业务请求,实现代码如下:
/** * 服务器端 */ class MySocketServer { public static void main(String[] args) throws IOException { // 创建 Socket 服务器端 ServerSocket serverSocket = new ServerSocket(9093); // 获取客户端连接 Socket clientSocket = serverSocket.accept(); // 使用线程池处理更多的客户端 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(100, 150, 100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000)); threadPool.submit(() -> { // 客户端消息处理 processMessage(clientSocket); }); } /** * 客户端消息处理 * @param clientSocket */ private static void processMessage(Socket clientSocket) { // Socket 封装对象 SocketPacket socketPacket = new SocketPacket(); // 获取客户端发送的消息对象 try (InputStream inputStream = clientSocket.getInputStream()) { while (true) { // 获取消息头(也就是消息体的长度) int bodyLength = socketPacket.getHeader(inputStream); // 消息体 byte 数组 byte[] bodyByte = new byte[bodyLength]; // 每次实际读取字节数 int readCount = 0; // 消息体赋值下标 int bodyIndex = 0; // 循环接收消息头中定义的长度 while (bodyIndex <= (bodyLength - 1) && (readCount = inputStream.read(bodyByte, bodyIndex, bodyLength)) != -1) { bodyIndex += readCount; } bodyIndex = 0; // 成功接收到客户端的消息并打印 System.out.println("接收到客户端的信息:" + new String(bodyByte)); } } catch (IOException ioException) { System.out.println(ioException.getMessage()); } } }
以上程序的执行结果如下:
从上述结果可以看出,消息通讯正常,客户端和服务器端的交互中并没有出现粘包和半包的问题。