Java nio包SocketChannel详解

Java NIO Channel 使用 Java NIO 中的 Channel 分类: FileChannel SocketChannel ServerSocketChannel DatagramChannel FileChannel: 主要用于文件的读写,可以从磁盘上读取文件,也可以向磁盘上写入文件。 SocketChannel:用于 Socket 的 TCP 连接的数据读写,既可以从 Channel 读数据,也可以向 Channle 中写入数据 ServerSocketChannel:通过 ServerSocketChanne 阅读详情

目录

一、Selector详解

1. 打开 Selector

2. 向 Selector 注册通道

3. 选择操作

4. 获取已选择的键集合

5. 处理事件

6. 取消键

7. 关闭 Selector

二、SocketChannel详解

1. 打开 SocketChannel

2. 连接到服务器

3. 读取数据

4. 写入数据

使用 write() 方法将数据从 ByteBuffer 写入到 SocketChannel。

5. 非阻塞模式

6. 关闭 SocketChannel

7. Selector 与 SocketChannel


SocketChannel 是 Java NIO 中用于实现基于 TCP 协议的套接字通信的通道。在介绍SocketChannel之前先讲下Selector 。

一、Selector详解

Selector 是 Java NIO 中的一个关键组件,用于实现非阻塞 I/O 操作。它允许一个线程管理多个通道,通过选择器监听通道上是否有事件发生,从而实现单线程处理多个通道的 I/O 操作。以下是 Selector 的一些关键操作:

1. 打开 Selector

使用 Selector.open() 静态方法打开一个 Selector。

Selector selector = Selector.open();
2. 向 Selector 注册通道

通过 register() 方法向 Selector 注册通道,并指定要监听的事件类型(如读、写等)。

SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
3. 选择操作

调用 select() 方法选择通道上的操作。这个方法是阻塞的,直到至少有一个注册的通道有事件发生。

int selectedChannels = selector.select();
4. 获取已选择的键集合

使用 selectedKeys() 方法获取已选择的键集合,表示那些通道上有事件发生。

Set<SelectionKey> keys = selector.selectedKeys();
5. 处理事件

遍历已选择的键集合,处理每个键对应的通道上发生的事件。

for (SelectionKey key : keys) {
    if (key.isReadable()) {
        // 处理读事件
    } else if (key.isWritable()) {
        // 处理写事件
    }
    // 其他事件类型的处理...
}
6. 取消键

使用 cancel() 方法取消一个键的注册。

key.cancel();
7. 关闭 Selector

使用 close() 方法关闭 Selector。

以下是一个简单的示例演示了如何使用 Selector 监听多个通道的读写事件:

import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class SelectorExample {
    public static void main(String[] args) {
        try {
            // 打开 Selector
            Selector selector = Selector.open();

            // 向 Selector 注册通道
            SocketChannel channel1 = SocketChannel.open();
            channel1.configureBlocking(false);
            channel1.register(selector, SelectionKey.OP_READ);

            SocketChannel channel2 = SocketChannel.open();
            channel2.configureBlocking(false);
            channel2.register(selector, SelectionKey.OP_WRITE);

            // 选择操作
            int selectedChannels = selector.select();

            // 获取已选择的键集合
            Set<SelectionKey> keys = selector.selectedKeys();

            // 处理事件
            Iterator<SelectionKey> iterator = keys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();

                if (key.isReadable()) {
                    // 处理读事件
                } else if (key.isWritable()) {
                    // 处理写事件
                }

                // 其他事件类型的处理...

                // 取消键,防止重复处理
                iterator.remove();
            }

            // 关闭 Selector
            selector.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这个示例创建了两个非阻塞的 SocketChannel,并注册到一个 Selector 上,然后通过 select() 方法选择通道上的操作。

二、SocketChannel详解

SocketChannel 是 Java NIO 中用于实现基于 TCP 协议的套接字通信的通道。它提供了非阻塞的、可选择的、双向的连接,可以用于在客户端和服务器之间进行网络通信。

1. 打开 SocketChannel

可以通过 SocketChannel.open() 静态方法来打开一个 SocketChannel。

SocketChannel socketChannel = SocketChannel.open();
2. 连接到服务器

使用 connect() 方法连接到服务器。SocketChannel 是非阻塞的,因此 connect() 方法可能在连接建立之前返回。

socketChannel.connect(new InetSocketAddress("example.com", 80));
3. 读取数据

使用 read() 方法从 SocketChannel 读取数据到 ByteBuffer 中。

ByteBuffer buffer = ByteBuffer.allocate(1024); 
int bytesRead = socketChannel.read(buffer);
4. 写入数据
使用 write() 方法将数据从 ByteBuffer 写入到 SocketChannel。
ByteBuffer buffer = ByteBuffer.wrap("Hello, Server!".getBytes());
int bytesWritten = socketChannel.write(buffer);
5. 非阻塞模式

SocketChannel 默认是阻塞的,可以通过调用 configureBlocking(false) 将其设置为非阻塞模式。

socketChannel.configureBlocking(false);
6. 关闭 SocketChannel

使用 close() 方法关闭 SocketChannel。

socketChannel.close();
7. Selector 与 SocketChannel

结合 Selector 使用,可以实现多路复用,使得一个线程可以处理多个 SocketChannel。

Selector selector = Selector.open();

SocketChannel channel1 = SocketChannel.open();
channel1.configureBlocking(false);
channel1.register(selector, SelectionKey.OP_READ);

SocketChannel channel2 = SocketChannel.open();
channel2.configureBlocking(false);
channel2.register(selector, SelectionKey.OP_WRITE);

以下是一个简单的示例,演示了如何使用 SocketChannel 进行连接和数据传输:

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class SocketChannelExample {
    public static void main(String[] args) {
        try {
            // 打开 SocketChannel
            SocketChannel socketChannel = SocketChannel.open();

            // 设置为非阻塞模式
            socketChannel.configureBlocking(false);

            // 连接到服务器
            socketChannel.connect(new InetSocketAddress("example.com", 80));

            // 等待连接完成
            while (!socketChannel.finishConnect()) {
                // 可以在这里做其他事情,不阻塞
            }

            // 发送数据
            String message = "Hello, Server!";
            ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
            while (buffer.hasRemaining()) {
                socketChannel.write(buffer);
            }

            // 接收数据
            ByteBuffer readBuffer = ByteBuffer.allocate(1024);
            int bytesRead = socketChannel.read(readBuffer);

            while (bytesRead != -1) {
                readBuffer.flip();
                while (readBuffer.hasRemaining()) {
                    System.out.print((char) readBuffer.get());
                }
                readBuffer.clear();
                bytesRead = socketChannel.read(readBuffer);
            }

            // 关闭 SocketChannel
            socketChannel.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

总体而言,SocketChannel 提供了一种灵活、高效的方式来进行基于 TCP 的网络通信。

Java千百问_01基本概念(013)_Socket、SocketChannel有什么区别 点击进入_更多_Java千百问1、Socket、SocketChannel有什么区别了解Socket看这里:Socket是什么 Socket、SocketChannel二者的实质都是一样的,都是为了实现客户端与服务器端的连接而存在的,但是在使用上,却有很大的区别。具体如下:所属包不同 Socket在java.net包中,而SocketChannel在java.nio包中。异步方式不同 从包的不 阅读详情

相关推荐

76、Java NIO 及子包详解

本文详细介绍了 Java NIO 及其子包的核心类和接口,包括 ServerSocketChannel、SocketChannel、Selector、Charset 等,并通过代码示例展示了它们在网络通信和字符编码解码中的应用。同时,文章还探讨了异常处理策略和性能优化建议,帮助开发者更好地理解和使用 Java NIO 的强大功能。

vscode6remote的博客 58

NIO之SocketChannel,SocketChannel ,DatagramChannel解读

(1)SocketChannel 就是 NIO 对于非阻塞 socket 操作的支持的组件,其在 socket 上 封装了一层,主要是支持了非阻塞的读写。同时改进了传统的单向流 API,,Channel同时支持读写。(2)socket 通道类主要分为 DatagramChannel、SocketChannel 和 ServerSocketChannel,它们在被实例化时都会创建一个对等 socket 对象。

一个菜鸡的博客 2701

SocketChannel、ServerSocketChannel与Selector的实际案例

一个关于SocketChannel、ServerSocketChannel、Selector的综合案例

【NIO】SocketChannel

前言 Github:https://github.com/yihonglei/java-all Project:java-nio Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。如下2种方式创建SocketChannel: 1)打开一个SocketChannel并连接到互联网上的某台服务器。 2)一个新连接到达ServerSocketChannel时,会...

yhl_jxy的博客 5198

java的ServerSocketChannel与SocketChannel的使用

java的ServerSocketChannel与SocketChannel的使用

KEGG数据库与KAAS工具:基因功能注释的实用指南

本文提供了使用KEGG数据库与KAAS工具进行基因功能注释的完整实用指南。详细阐述了如何从准备基因或蛋白序列开始,通过KAAS服务器获取KEGG Orthology(KO)编号,并解读注释结果。文章进一步介绍了如何利用KOBAS工具进行通路富集分析,将定性观察转化为定量洞察,并分享了提高注释准确率、处理大数据集及使用API等避坑技巧与高阶方法,为基因组学、转录组学研究者奠定坚实的数据分析基础。

weixin_29292535的博客 390

java 中nio包的FileChannel,DatagramChannel,SocketChannel,ServerSocketChannel类编程

nio实现多并发音乐

weixin_66060122的博客 246

GT-suite v2016的下载和安装

1 写在前面 GT-suite 是一款用来做内燃机仿真的软件。在安装过程中遇到很多问题,网上的安装教程也大都抄来抄去,试着安装了几遍都没有成功。最终在贴吧一个老哥的帖子里找到了解决办法,但是老哥的帖子也不是很详细,所以做了这个详细版本的教程。 GT-suite v2016安装包: 链接:https://pan.baidu.com/s/1JZPgJ8_-J-L8rV84-eHedQ 提取码:uj...

kisssshot的博客 3万+

可使用Java中Nio包的socketChannel从客户端套接字获取的最大数据大小

使用SocketChannel sc =(SocketChannel)key.channel();,我们可以从端口获取数据到缓冲区. 为了从端口连续接收数据而不会丢失数据,代码应如何? 这是我的代码 import java.io.*; import java.net.*; import java.nio.*; import java.nio.channels.*; import ...

weixin_44109689的博客 958

不用写代码!用AIStarter 5.0.0离线包部署InfiniteTalk的完整指南(Windows/Mac/Linux全平台)

本文详细介绍了如何使用AIStarter 5.0.0离线包在Windows、Mac和Linux平台上零代码部署InfiniteTalk数字人。从环境准备、离线资源获取与验证,到全平台部署实操指南,提供了完整的本地化安装流程和优化建议,帮助用户快速实现AI项目的一键部署。

weixin_30275415的博客 273

Containerd容器运行时的私有仓库镜像推送push和镜像拉取问题解决

向/etc/containerd/config.toml配置添加如下配置,然后重启containerd。向/etc/containerd/config.toml配置添加如下配置,然后重启containerd。通过crictl为k8s拉取镜像如下所示。可以通过ctr命令进行镜像推送。往私有仓库推送镜像如下。

Bulut0907 1万+

Java 用NIO实现一个聊天室(多人聊天、单人聊天)

这两行代码由于前后发送,所以client这个channel会先后收到 昵称验证通过 和 推送上线 的消息,如果tcp在传输过程中足够快,那么客户端在一次read事件中,会把两次消息一次性读出来。而由于这个代码写的比较简陋,在tcp的传输内容上并没有建立起足够安全的内容协议(比如消息与消息用特定的分隔符、或者用前面的几个字节来标注内容的实际字节数),所以上述代码并不能两次消息分开了。 造成的问题是:客户端是通过服务端回复的 验证消息 来初始化姓名的,如果粘包情况出现,那么客户端将会把真正的姓名和上线消息合起

anlian523的博客 2327

手把手教你用Node.js模拟大麦APP下单请求(含滑块验证处理)

本文详细解析了如何使用Node.js模拟大麦APP下单请求的全流程,包括接口逆向、滑块验证处理和签名算法逆向等关键技术。通过实战案例和代码示例,帮助开发者掌握移动端API调用的核心要素,如动态参数构造、安全验证突破等,提升自动化下单的成功率和效率。

weixin_42569329的博客 353

【NIO与Netty】Java NIO入门:多线程多Selector模式,零拷贝,同步阻塞、同步非阻塞、同步多路复用、异步非阻塞的区别

尚硅谷+黑马 学习总结:从操作系统的底层逻辑解释同步阻塞、同步非阻塞、同步多路复用、异步非阻塞的区别,分析零拷贝的概念。多线程多Selector模式

知识输出、记录学习 1640

【HSPiP应用指南】从理论到实践:如何利用汉森溶解度参数优化配方设计

本文深入解析了汉森溶解度参数(HSP)理论及其在配方设计中的核心价值,并详细介绍了如何利用HSPiP软件工具从理论走向实践。文章通过匹配溶解度参数、计算汉森距离(Ra),系统阐述了如何解决溶剂选择、颜料分散稳定性及扩散行为预测等关键问题,并结合界面气相色谱(IGC)等实验方法提升预测精度,旨在帮助配方师实现配方设计的可视化、可量化与高效优化。

weixin_29305313的博客 1646

Ubuntu中交叉编译armadillo库

网上关于交叉编译armdillo库比较少,借鉴了一些但是在前几天编译时总是磕磕绊绊,于是写一个详细的编译过程。交叉编译armdillo库包含两个步骤:交叉编译依赖库和交叉编译armdillo库。

weixin_39813867的博客 1879

SocketChannel与ServerSocketChannel区别

(1)Socket 和ServerSocke 是一对 他们是java.net下面实现socket通信的类 (2) SocketChannel 和ServerSocketChannel是一对 他们是java.nio下面实现通信的类 支持异步通信 (3)服务器必须先建立ServerSocket或者ServerSocketChannel 来等待客户端的连接 (4)客户端必须建立相对应的Socke...

那一年那一夏 8146

CentOS7 安装天气分型软件cost733过程详解

cost733是一款天气分型软件,其内置的一些算法可以帮助气象工作者进行天气类型划分等(我也是初学者,仅仅知道一些皮毛),但是网上找到的安装办法比较少,并且总会出现一些报错,试了一晚上,终于将安装办法调通了,希望可以帮助到大家

weixin_62573024的博客 3562

java之nio总结

/** * java.net包中包含的都是最原始网络应用程序设施,包括 Socket, InetSocketAddress * * java.nio包中包含最新的网络应用构建基础设施,包括buf和channel * * SocketChannel.open()方法 * SelectorProvider.select() --> SelectorProvider实例 * * ServerSocketChannel.open ===> SelectorProvider.openSe.

ZHANGJNWEI的专栏 145

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

10 客户端代码Demo(NIO)

如何用java.nio包中的类来创建客户程序EchoClient,本节提供了两种实现方式: 采用阻塞模式,单线程。 采用非阻塞模式,单线程。 文章目录1 采用阻塞模式,单线程2 采用非阻塞模式,单线程 1 采用阻塞模式,单线程 这个已经在服务端代码Demo(NIO)中提到了,代码如下: package study.wyy.net.nio.client; import lombok.Builder; import lombok.extern.slf4j.Slf4j; import java.io.*;

wyaoyao93的博客 496

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Java NIO 随笔(二)

Java NIO数据通道传输: RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw"); FileChannel fromChannel = fromFile.getChannel(); RandomAccessFile toFile = new RandomAccessFile("toFile.tx

fanwb1985的专栏 326

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

java中非阻塞网络编程中NIO知识点介绍

java.nio包中的主要类 1.ServerSocketChanne类:ServerSocket的替代类,支持阻塞通信与费阻塞通信。 2.SocketChannel类:Socket的替代类,支持阻塞通信与非阻塞通信。 3.Selector类:为ServerSocketChannel监控接收连接就绪事件,为SocketChannel监控连接就绪、读就绪、写就绪等事件。 4.Selectio

zzjstudent的专栏 720

《精通并发与Netty》学习笔记(12 - 详解NIO (三) SocketChannel、Pipe)

一、SocketChannelJava NIO中的SocketChannel是一个连接到TCP网络套接字的通道。可以通过以下2种方式创建SocketChannel: 打开一个SocketChannel并连接到互联网上的某台服务器。一个新连接到达ServerSocketChannel时,会创建一个SocketChannel。 打开 SocketChannel下面是SocketChannel的打开...

weixin_30662109的博客 194

Java NIO 有着一篇足够入门

万字图文,一篇带你入门 NIO,绝对精彩,干货满满

小王是个弟弟 481

java NIO概述

一 什么是线层阻塞? 线程阻塞即线程高风亮节让出或放弃CPU,暂停执行,只有等到导致阻塞的原因解除,才能恢复运行;或者被其他线程中断,该线程会退出阻塞状态,并且抛出InterrutedException. 二 常见的导致线程阻塞的原因: 线程执行了Thread.sleep(intn)方法,线程放弃CPU,睡眠n毫秒,然后恢复运行。但是此时被该线程所控制的同步代码...

gaoxueyi551的专栏 1570

java.nio包的分析(二)---Channels分析

继上一小节分析完

走在前往架构师的路上 1882
上一篇: Java nio包FileChannel详解
下一篇: Java -jar参数详解
境里婆娑
境里婆娑 新星创作者: Java技术领域 新星创作者: Java技术领域 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄10年 1万+粉丝 300原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

境里婆娑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值