- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
在 scatter-and-gather 场景下,可以将数据写入多个 Buffer 中。在 NIO 中,也能够同时操作多个缓冲区。在很多 Channel 实现类中,都提供了多个重载的 read() 和 write() 方法,下表介绍了 SocketChannel 的 read() 和 write() 方法。
| <br>read() 的重载方法<br> | <br>简介<br> |
| <br>int read(ByteBuffer dst)<br> | <br>将 Channel 读取到的数据存入一个 ByteBuffer 中<br> |
| <br>long read(ByteBuffer[] dsts,int offset,int length) <br><br>long read(ByteBuffer[] dsts)<br> | <br>将 Channel 读取到的数据存入一个 ByteBuffer 数组中 <br> |
| <br>write() 的重载方法<br> | <br>简介<br> |
| <br>int write(ByteBuffer srcs)<br> | <br>将 ByteBuffer 中的数据写入 Channel 中<br> |
| <br>long write(ByteBuffer[] srcs,int offset,int length)<br><br>long write(ByteBuffer[] srcs)<br> | <br>将 ByteBuffer 数组中的所有数据写入 Channel 中<br> |
package nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
public class NIOServerWith2Buffers {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
ServerSocket serverSocket = serverSocketChannel.socket();
serverSocket.bind(new InetSocketAddress(8888)) ;
ByteBuffer[] buffers = new ByteBuffer[2] ;
buffers[0] = ByteBuffer.allocate(4) ;
buffers[1] = ByteBuffer.allocate(8) ;
int bufferSum = 4 + 8 ;
SocketChannel socketChannel = serverSocketChannel.accept();
while(true){
/*
读取客户端的消息:
eachReadbytes:每次读取到的字节数
totalReadBytes:当前时刻,一共读取的字节数
如果 totalReadBytes 小于 "buffers能够容纳的最大字节数",则循环累加读取;否则,清空buffers,重新读取
*/
int totalReadBytes = 0 ;
while(totalReadBytes < bufferSum){
long eachReadbytes = socketChannel.read(buffers);
totalReadBytes += eachReadbytes ;
System.out.println("读取到的数据大小:" + eachReadbytes);
}
// 如果buffers已满
for(ByteBuffer buffer : buffers) {
buffer.flip() ;
}
}
}
}
package nio;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
/**
* @className: ChatClient
* @description: 客户端
* @date: 2022/5/23
* @author: cakin
*/
public class ChatClient {
public static void main(String[] args) {
try {
SocketChannel socketChannel = SocketChannel.open();
// 切换到非阻塞模式
socketChannel.configureBlocking(false);
Selector selector = Selector.open();
// 在客户端的选择器上,注册一个通道,并标识该通道所感兴趣的事件是:向服务端发送连接(连接就绪)。对应于服务端的OP_ACCEPT事件
socketChannel.register(selector, SelectionKey.OP_CONNECT);
socketChannel.connect(new InetSocketAddress("127.0.0.1", 8888));
while (true) {
selector.select();
// selectionKeys 包含了所有通道与选择器之间的关系(请求连接、读、写)
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey selectedKey = keyIterator.next();
// 判断是否连接成功
if (selectedKey.isConnectable()) {
ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
// 创建一个用于和服务端交互的 Channel
SocketChannel client = (SocketChannel) selectedKey.channel();
// 如果状态是:正在连接中...
if (client.isConnectionPending()) {
boolean isConnected = client.finishConnect();
if (isConnected) {
System.out.println("连接成功!访问的端口是:" + port);
// 向服务端发送一条测试消息
sendBuffer.put("connecting".getBytes());
sendBuffer.flip();
client.write(sendBuffer);
}
// 在“聊天室”中,对于客户端而言,可以随时向服务端发送消息(写操作),因此,需要建立一个单独写线程
new Thread(() -> {
while (true) {
try {
sendBuffer.clear();
// 接收用户从控制台输入的内容,并发送给服务端
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader bReader = new BufferedReader(reader);
String message = bReader.readLine();
sendBuffer.put(message.getBytes());
sendBuffer.flip();
client.write(sendBuffer);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
// 标记通道感兴趣的事件是:读取服务端消息(读就绪)
client.register(selector, SelectionKey.OP_READ);
// 客户端读取服务端的反馈消息
} else if (selectedKey.isReadable()) {
SocketChannel client = (SocketChannel) selectedKey.channel();
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
// 将服务端的反馈消息放入 readBuffer中
int len = client.read(readBuffer);
if (len > 0) {
String receive = new String(readBuffer.array(), 0, len);
System.out.println(receive);
}
}
}
selectionKeys.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
连接成功!访问的端口是:8888
helloserver
byebye
读取到的数据大小:10
读取到的数据大小:2
读取到的数据大小:9
读取到的数据大小:3
读取到的数据大小:3
问题情景 混淆群内的小伙伴遇到这么个问题,Mailivery 这个网站登录后,明明提交的表单(邮箱和密码也正确)、请求头等等都没问题,为啥一直重定向到登录页面呢?唉,该出手时就出手啊,我也看看咋回事
实战-行业攻防应急响应 简介: 服务器场景操作系统 Ubuntu 服务器账号密码:root/security123 分析流量包在/home/security/security.pcap 相
背景 最近公司将我们之前使用的链路工具切换为了 OpenTelemetry. 我们的技术栈是: OTLP C
一 同一类的方法都用 synchronized 修饰 1 代码 package concurrent; import java.util.concurrent.TimeUnit; public c
一 简单例子 1 代码 package concurrent.threadlocal; /** * ThreadLocal测试 * * @author cakin */ public class T
1. 问题背景 问题发生在快递分拣的流程中,我尽可能将业务背景简化,让大家只关注并发问题本身。 分拣业务针对每个快递包裹都会生成一个任务,我们称它为 task。task 中有两个字段需要
实战环境 elastic search 8.5.0 + kibna 8.5.0 + springboot 3.0.2 + spring data elasticsearch 5.0.2 +
Win10下yolov8 tensorrt模型加速部署【实战】 TensorRT-Alpha 基于tensorrt+cuda c++实现模型end2end的gpu加速,支持win10、
yolov8 tensorrt模型加速部署【实战】 TensorRT-Alpha 基于tensorrt+cuda c++实现模型end2end的gpu加速,支持win10、linux,
目录如下: 为什么需要自定义授权类型? 前面介绍OAuth2.0的基础知识点时介绍过支持的4种授权类型,分别如下: 授权码模式 简化模式 客户端模式 密码模式
今天这篇文章介绍一下如何在修改密码、修改权限、注销等场景下使JWT失效。 文章的目录如下: 解决方案 JWT最大的一个优势在于它是无状态的,自身包含了认证鉴权所需要的所有信息,服务器端
前言 大家好,我是捡田螺的小男孩。(求个星标置顶) 我们日常做分页需求时,一般会用limit实现,但是当偏移量特别大的时候,查询效率就变得低下。本文将分四个方案,讨论如何优化MySQL百万数
前言 大家好,我是捡田螺的小男孩。 平时我们写代码呢,多数情况都是流水线式写代码,基本就可以实现业务逻辑了。如何在写代码中找到乐趣呢,我觉得,最好的方式就是:使用设计模式优化自己
我们先讲一些arm汇编的基础知识。(我们以armv7为例,最新iphone5s上的64位暂不讨论) 基础知识部分: 首先你介绍一下寄存器: r0-r3:用于函数参数及返回值的传递 r4-r6
一 同一类的静态方法都用 synchronized 修饰 1 代码 package concurrent; import java.util.concurrent.TimeUnit; public
DRF快速写五个接口,比你用手也快··· 实战-DRF快速写接口 开发环境 Python3.6 Pycharm专业版2021.2.3 Sqlite3 Django 2.2 djangorestfram
一 添加依赖 org.apache.thrift libthrift 0.11.0 二 编写 IDL 通过 IDL(.thrift 文件)定义数据结构、异常和接口等数据,供各种编程语言使用 nam
我正在阅读 Redis in action e-book关于semaphores的章节.这是使用redis实现信号量的python代码 def acquire_semaphore(conn, semn
自定义控件在WPF开发中是很常见的,有时候某些控件需要契合业务或者美化统一样式,这时候就需要对控件做出一些改造。 目录 按钮设置圆角
师父布置的任务,让我写一个服务练练手,搞清楚socket的原理和过程后跑了一个小demo,很有成就感,代码内容也比较清晰易懂,很有教育启发意义。 代码 ?
我是一名优秀的程序员,十分优秀!