JAVA异步的TCP 通讯-客户端

news2025/2/6 14:57:27

一、客户端代码示例

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AdvancedAsyncTCPClient {
    private static final String SERVER_HOST = "localhost";
    private static final int SERVER_PORT = 8888;
    private static final int BUFFER_SIZE = 1024;
    private final AsynchronousSocketChannel clientChannel;
    private final ExecutorService threadPool;

    public AdvancedAsyncTCPClient() throws IOException {
        // 创建异步套接字通道
        clientChannel = AsynchronousSocketChannel.open();
        // 创建一个固定大小的线程池,用于处理业务逻辑
        threadPool = Executors.newFixedThreadPool(5);
    }

    public void connect() {
        // 异步连接到服务器
        clientChannel.connect(new InetSocketAddress(SERVER_HOST, SERVER_PORT), null, new CompletionHandler<Void, Void>() {
            @Override
            public void completed(Void result, Void attachment) {
                System.out.println("Connected to server: " + SERVER_HOST + ":" + SERVER_PORT);
                // 连接成功后开始读取服务器数据
                startReading();
                // 发送初始消息
                sendMessage("Hello, server!");
            }

            @Override
            public void failed(Throwable exc, Void attachment) {
                System.err.println("Failed to connect to server: " + exc.getMessage());
                closeChannel();
            }
        });
    }

    private void startReading() {
        ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
        // 异步读取服务器数据
        clientChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer bytesRead, ByteBuffer buffer) {
                if (bytesRead > 0) {
                    buffer.flip();
                    byte[] data = new byte[buffer.remaining()];
                    buffer.get(data);
                    String message = new String(data);
                    System.out.println("Received message from server: " + message);
                    // 继续读取服务器数据
                    buffer.clear();
                    clientChannel.read(buffer, buffer, this);
                } else if (bytesRead == -1) {
                    // 服务器关闭连接
                    System.out.println("Server closed the connection");
                    closeChannel();
                }
            }

            @Override
            public void failed(Throwable exc, ByteBuffer buffer) {
                System.err.println("Failed to read data from server: " + exc.getMessage());
                closeChannel();
            }
        });
    }

    public void sendMessage(String message) {
        ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
        // 异步发送消息到服务器
        clientChannel.write(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer bytesWritten, ByteBuffer buffer) {
                if (buffer.hasRemaining()) {
                    // 如果还有数据未发送完,继续发送
                    clientChannel.write(buffer, buffer, this);
                } else {
                    System.out.println("Message sent to server: " + message);
                }
            }

            @Override
            public void failed(Throwable exc, ByteBuffer buffer) {
                System.err.println("Failed to send message to server: " + exc.getMessage());
                closeChannel();
            }
        });
    }

    private void closeChannel() {
        try {
            System.out.println("Closing client connection");
            clientChannel.close();
            threadPool.shutdown();
        } catch (IOException e) {
            System.err.println("Error closing client channel: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        try {
            AdvancedAsyncTCPClient client = new AdvancedAsyncTCPClient();
            client.connect();
        } catch (IOException e) {
            System.err.println("Error creating client: " + e.getMessage());
        }
    }
}

二、代码分析

AdvancedAsyncTCPClient 类

  1. 构造函数:创建 AsynchronousSocketChannel 并初始化一个固定大小的线程池

  2. connect() 方法:异步连接到服务器,连接成功后开始读取服务器数据并发送初始消息。

  3. startReading() 方法:异步读取服务器发送的数据,使用 CompletionHandler 处理读取结果。

  4. sendMessage() 方法:异步发送消息到服务器,处理可能的未发送完的数据。

  5. closeChannel() 方法:关闭客户端通道并关闭线程池,处理关闭过程中可能出现的异常。

CompletionHandler

  1. 在 connect()startReading() 和 sendMessage() 方法中使用 CompletionHandler 来处理异步操作的完成结果。
  2. completed() 方法处理操作成功的情况,failed() 方法处理操作失败的情况。

线程池

        1.使用 Executors.newFixedThreadPool(5) 创建一个固定大小的线程池,用于处理业务逻辑,避免阻塞 I/O 操作。

三、优点

  • 异步 I/O:利用 Java NIO 2 的异步 I/O 特性,提高了客户端的并发处理能力。
  • 线程池:使用线程池处理业务逻辑,减少了线程创建和销毁的开销。
  • 异常处理:对各种异常情况进行了处理,增强了代码的健壮性。
  • 资源管理:在关闭客户端时,正确关闭客户端通道和线程池,避免资源泄漏。

四、注意事项

  • 该示例假设服务器运行在 localhost 的 8888 端口,你可以根据实际情况修改 SERVER_HOST 和 SERVER_PORT
  • 此代码只是一个基础示例,实际应用中可能需要根据具体需求进行扩展,如处理更复杂的消息格式、实现重连机制等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2293838.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java进阶之并发编程一ReentrantLock的实际应用和线程中断EXAMPLE

引言:继上一篇ReentrantLock的介绍来做俩个小demo。 实现3个线程分别打印指定数字和线程死锁进行线程中断。 上一篇:<<java进阶之并发编程一ReentrantLock同步锁的学习和syncthronized的区别>> **demo1:**ReentrantLock搭配三个线程分别打印指定的数字,直接上代…

分享2款 .NET 开源且强大的翻译工具

前言 对于程序员而言永远都无法逃避和英文打交道&#xff0c;今天大姚给大家分享2款 .NET 开源、功能强大的翻译工具&#xff0c;希望可以帮助到有需要的同学。 STranslate STranslate是一款由WPF开源的、免费的&#xff08;MIT License&#xff09;、即开即用、即用即走的翻…

SpringBoot+Dubbo+zookeeper 急速入门案例

项目目录结构&#xff1a; 第一步&#xff1a;创建一个SpringBoot项目&#xff0c;这里选择Maven项目或者Spring Initializer都可以&#xff0c;这里创建了一个Maven项目&#xff08;SpringBoot-Dubbo&#xff09;&#xff0c;pom.xml文件如下&#xff1a; <?xml versio…

[LeetCode] 二叉树 I — 深度优先遍历(前中后序遍历) | 广度优先遍历(层序遍历):递归法迭代法

二叉树 基础知识深度优先遍历递归法迭代法&#xff08;栈&#xff09;144# 二叉树的前序遍历94# 二叉树的中序遍历145# 二叉树的后序遍历 广度优先遍历递归法迭代法&#xff08;队列&#xff09;102# 二叉树的层序遍历107# 二叉树的层序遍历 II199# 二叉树的右视图637# 二叉树的…

Python aiortc API

本研究的主要目的是基于Python aiortc api实现抓取本地设备&#xff08;摄像机、麦克风&#xff09;媒体流实现Web端预览。本文章仅仅描述实现思路&#xff0c;索要源码请私信我。 demo-server解耦 原始代码解析 http服务器端 import argparse import asyncio import json…

OpenCV4,快速入门,第二讲:图像色彩空间转换

文章目录 引言一、色彩空间概述1.1 RGB与HSV的区别1.2 HSV的详细含义cvtColor二、cvtColor函数详解2.1 函数原型2.2 参数说明2.3 使用示例三、imwrite函数详解3.1 函数原型3.2 参数说明3.3 使用示例四、完整示例代码五、应用场景与注意事项5.1 HSV的典型应用5.2 注意事项结语引…

86.(2)攻防世界 WEB PHP2

之前做过&#xff0c;回顾一遍&#xff0c;详解见下面这篇博客 29.攻防世界PHP2-CSDN博客 既然是代码审计题目&#xff0c;打开后又不显示代码&#xff0c;肯定在文件里 <?php // 首先检查通过 GET 请求传递的名为 "id" 的参数值是否严格等于字符串 "admi…

RK3588——解决Linux系统触摸屏坐标方向相反问题

问题描述&#xff1a;触摸正常产生中断&#xff0c;但系统上报的触摸坐标不正确&#xff0c;是反向的坐标。 解决办法通过修改设备树添加属性翻转坐标。 注&#xff1a;需确认对应的驱动是否有解析该属性的具体内容&#xff0c;否则仍然无法生效。

面对全球化的泼天流量,出海企业如何观测多地域网络质量?

作者&#xff1a;俞嵩、白玙 泼天富贵背后&#xff0c;技术挑战接踵而至 随着全球化进程&#xff0c;出海、全球化成为很多 Toc 产品的必经之路&#xff0c;保障不同地域、不同网络环境的一致的用户体验成为全球化应用的不得不面对的问题。在跨运营商、跨地域的网络环境中&am…

YOLOv11实时目标检测 | 摄像头视频图片文件检测

在上篇文章中YOLO11环境部署 || 从检测到训练https://blog.csdn.net/2301_79442295/article/details/145414103#comments_36164492&#xff0c;我们详细探讨了YOLO11的部署以及推理训练&#xff0c;但是评论区的观众老爷就说了&#xff1a;“博主博主&#xff0c;你这个只能推理…

自定义序列化数据类型

目录 1. WritableComparable1.1 Writable1.2 Comparable1.3 IntWritable 2. 自定义序列化数据类型RectangleWritable3. 矩形面积计算3.1 Map3.2 Reduce 4. 代码和结果4.1 pom.xml中依赖配置4.2 工具类util4.3 矩形面积计算4.4 结果 参考 本文引用的Apache Hadoop源代码基于Apac…

【Linux网络编程】:URL(encode),HTTP协议,telnet工具

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ Linux网络编程笔记&#xff1a; https://mp.csdn…

C语言基础系列【3】VSCode使用

前面我们提到过VSCode有多么的好用&#xff0c;本文主要介绍如何使用VSCode编译运行C语言代码。 安装 首先去官网&#xff08;https://code.visualstudio.com/&#xff09;下载安装包&#xff0c;点击Download for Windows 获取安装包后&#xff0c;一路点击Next就可以。 配…

学前端框架之前,你需要先理解 MVC

MVC 软件架构设计模式鼎鼎大名&#xff0c;相信你已经听说过了&#xff0c;但你确定自己已经完全理解到 MVC 的精髓了吗&#xff1f; 如果你是新同学&#xff0c;没听过 MVC&#xff0c;那可以到网上搜一些文章来看看&#xff0c;不过你要有心理准备&#xff0c;那些文章大多都…

Mysql:数据库

Mysql 一、数据库概念&#xff1f;二、MySQL架构三、SQL语句分类四、数据库操作4.1 数据库创建4.2 数据库字符集和校验规则4.3 数据库修改4.4 数据库删除4.4 数据库备份和恢复其他 五、表操作5.1 创建表5.2 修改表5.3 删除表 六、表的增删改查6.1 Create(创建):数据新增1&#…

熟练掌握Http协议

目录 基本概念请求数据Get请求方式和Post请求方式 响应数据响应状态码 基本概念 Http协议全称超文本传输协议(HyperText Transfer Protocol)&#xff0c;是网络通信中应用层的协议&#xff0c;规定了浏览器和web服务器数据传输的格式和规则 Http应用层协议具有以下特点&#…

C++的 I/O 流

本文把复杂的基类和派生类的作用和关系捋出来&#xff0c;具体的接口请参考相关文档 C的 I/O 流相关的类&#xff0c;继承关系如下图所示 https://zh.cppreference.com/w/cpp/io I / O 的概念&#xff1a;内存和外设进行数据交互称为 I / O &#xff0c;例如&#xff1a;把数…

【PDF多区域识别】如何批量PDF指定多个区域识别改名,基于Windows自带的UWP的文字识别实现方案

海关在对进口货物进行查验时,需要核对报关单上的各项信息。对报关单 PDF 批量指定区域识别改名后,海关工作人员可以更高效地从文件名中获取关键信息,如货物来源地、申报价值等。例如文件名 “[原产国]_[申报价值].pdf”,有助于海关快速筛选重点查验对象,提高查验效率和监管…

【大数据技术】本机PyCharm远程连接虚拟机Python

本机PyCharm远程连接虚拟机Python 注意:本文需要使用PyCharm专业版。 pycharm-professional-2024.1.4VMware Workstation Pro 16CentOS-Stream-10-latest-x86_64-dvd1.iso写在前面 本文主要介绍如何使用本地PyCharm远程连接虚拟机,运行Python脚本,提高编程效率。 注意: …

数字化转型:概念性名词浅谈(第四讲)

​大家好&#xff0c;本篇文章是在新年之际写的&#xff0c;所以在这里先给大家拜个年。 今天要介绍的名词为ETL: ETL&#xff0c;是英文Extract-Transform-Load的缩写&#xff0c;用来描述将数据从来源端经过抽取&#xff08;extract&#xff09;、转换&#xff08;transfor…