Socket的用法——NIO包下SocketChannel的用法 ———————————————— 版权声明:本文为CSDN博主「茶_小哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/ycgslh/article/details/79604074
服务端代码实现如下,其中包括一个静态内部类Handler来作为处理器,处理不同的操作。注意在遍历选择键集合时,没处理完一个操作,要将该请求在集合中移除。
/*
模拟服务端-nio-Socket实现
*/
public class NIOServer {
public static void main(String[] args) {
try {
//创建ServerSocketChannel通道,绑定监听端口为8080
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(8080));
//设置为非阻塞模式
serverSocketChannel.configureBlocking(false);
//注册选择器,设置选择器选择的操作类型
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//创建处理器
Handler handler = new Handler(1204);
while (true) {
//等待请求,每次等待阻塞3s,超过时间则向下执行,若传入0或不传值,则在接收到请求前一直阻塞
if (selector.select(3000) == 0) {
System.out.println("等待请求超时......");
continue;
}
System.out.println("-----处理请求-----");
//获取待处理的选择键集合
Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
while (keyIterator.hasNext()) {
SelectionKey selectionKey = keyIterator.next();
try {
//如果是连接请求,调用处理器的连接处理方法
if(selectionKey.isAcceptable()){
handler.handleAccept(selectionKey);
}
//如果是读请求,调用对应的读方法
if (selectionKey.isReadable()) {
handler.handleRead(selectionKey);
}
} catch (IOException e) {
keyIterator.remove();
continue;
}
}
//处理完毕从待处理集合移除该选择键
keyIterator.remove();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/*
处理器类
*/
private static class Handler{
private int bufferSize = 1024; //缓冲器容量
private String localCharset = "UTF-8"; //编码格式
public Handler(){}
public Handler(int bufferSize){
this(bufferSize,null);
}
public Handler(String localCharset){
this(-1,localCharset);
}
public Handler(int bufferSize,String localCharset){
if(bufferSize > 0){
this.bufferSize = bufferSize;
}
if(localCharset != null){
this.localCharset = localCharset;
}
}
/*
连接请求处理方法
*/
public void handleAccept(SelectionKey selectionKey) throws IOException {
//通过选择器键获取服务器套接字通道,通过accept()方法获取套接字通道连接
SocketChannel socketChannel = ((ServerSocketChannel)selectionKey.channel()).accept();
//设置套接字通道为非阻塞模式
socketChannel.configureBlocking(false);
//为套接字通道注册选择器,该选择器为服务器套接字通道的选择器,即选择到该SocketChannel的选择器
//设置选择器关心请求为读操作,设置数据读取的缓冲器容量为处理器初始化时候的缓冲器容量
socketChannel.register(selectionKey.selector(),SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize));
}
public void handleRead(SelectionKey selectionKey) throws IOException {
//获取套接字通道
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
//获取缓冲器并进行重置,selectionKey.attachment()为获取选择器键的附加对象
ByteBuffer byteBuffer = (ByteBuffer)selectionKey.attachment();
byteBuffer.clear();
//没有内容则关闭通道
if (socketChannel.read(byteBuffer) == -1) {
socketChannel.close();
} else {
//将缓冲器转换为读状态
byteBuffer.flip();
//将缓冲器中接收到的值按localCharset格式编码保存
String receivedRequestData = Charset.forName(localCharset).newDecoder().decode(byteBuffer).toString();
System.out.println("接收到客户端的请求数据:"+receivedRequestData);
//返回响应数据给客户端
String responseData = "已接收到你的请求数据,响应数据为:(响应数据)";
byteBuffer = ByteBuffer.wrap(responseData.getBytes(localCharset));
socketChannel.write(byteBuffer);
//关闭通道
socketChannel.close();
}
}
}
}
————————————————
版权声明:本文为CSDN博主「茶_小哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ycgslh/article/details/79604074
Socket的用法——NIO包下SocketChannel的用法 ———————————————— 版权声明:本文为CSDN博主「茶_小哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/ycgslh/article/details/79604074的更多相关文章
- 转载 WPF -- 控件模板 (ControlTemplate)(一) https://blog.csdn.net/qq_23018459/article/details/79899838
ControlTemplate(控件模板) https://blog.csdn.net/qq_23018459/article/details/79899838 WPF包含数据模板和控件模板,其中 ...
- 已知IP地址和子网掩码求出网络地址、广播地址、地址范围和主机数(转载https://blog.csdn.net/qq_39026548/article/details/78959089)
假设IP地址为128.11.67.31,子网掩码是255.255.240.0.请算出网络地址.广播地址.地址范围.主机数.方法:将IP地址和子网掩码转化成二进制形式,然后进行后续操作. IP地址和子网 ...
- 炸天的3D引擎OpenCASCADE的用法及案例(https://blog.csdn.net/xipengbozai/article/details/117044032?spm=1001.2014.3001.5502)
What CASCADE?Open CASCADE(简称OCC)平台是由法国Matra Datavision公司开发的CAD/CAE/CAM软件平台,可以说是世界上最重要的几何造型基础软件平台之一.开 ...
- 爬虫出现Forbidden by robots.txt(转载 https://blog.csdn.net/zzk1995/article/details/51628205)
先说结论,关闭scrapy自带的ROBOTSTXT_OBEY功能,在setting找到这个变量,设置为False即可解决. 使用scrapy爬取淘宝页面的时候,在提交http请求时出现debug信息F ...
- Mui本地打包笔记(一)使用AndroidStudio运行项目 转载 https://blog.csdn.net/baidu_32377671/article/details/79632411
转载 https://blog.csdn.net/baidu_32377671/article/details/79632411 使用AndroidStudio运行HBuilder本地打包的Mui项目 ...
- MVC和WebApi 使用get和post 传递参数。 转载https://blog.csdn.net/qq373591361/article/details/51508806
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq373591361/article/details/51508806我们总结一下用js请求服务器的 ...
- AutoFac控制反转 转载https://blog.csdn.net/u011301348/article/details/82256791
一.AutoFac介绍 Autofac是.NET里IOC(Inversion of Control,控制反转)容器的一种,同类的框架还有Spring.NET,Unity,Castle等.可以通过NuG ...
- IntelliJ Idea 常用快捷键列表 (需整理下) https://blog.csdn.net/dc_726/article/details/42784275
[常规] https://blog.csdn.net/dc_726/article/details/42784275https://jingyan.baidu.com/article/59a015e3 ...
- Postman用法简介----https://blog.csdn.net/flowerspring/article/details/52774399
https://blog.csdn.net/flowerspring/article/details/52774399 Postman用法简介
随机推荐
- Vitis AI--个人调试篇
一.下载VITIS-AI的仓库 单独git clone很慢,因此先将其导入到gitee平台,再执行clone 1. Import VITIS-AI github repo into gitee rep ...
- VS Code 自动化连接非固定IP地址EC2实例的解决方案
问题描述 大家可能和我一样,平时在AWS上启动一台安装有Linux EC2实例作为远程开发机. (注:这里的EC2实例是配置用私钥进行登录的) 通常,你可以选择申请一个Elastic IP绑定到这台开 ...
- [leetcode]54. Spiral Matrix2生成螺旋数组
import java.util.Arrays; /** * Created by lvhao on 2017/7/6. * Given an integer n, generate a square ...
- ESXi 中重新启动管理代理
使用直接控制台用户界面 (DCUI)重启管理代理: 连接到您的 ESXi 主机的控制台. 按 F2 自定义系统. 以 root 身份登录. 使用上下箭头导航至故障排除选项>重新启动管理代理. 按 ...
- webapplicationContext之ServletContext等相关概念说明
1)ServletContext是一个全局的储存信息的空间,所有用户共用一个,其信息必须是线程安全且共享的. ServletContext有一个接口定义:ServletContext接口.此接口定义了 ...
- 多线程应用之调用start()方法和run()方法的区别
今天在做项目的时候,遇到一个问题,两个一模一样的demo,运行出来的效果却一点也不一样,找了半天,就是有一行代码不同,一个是thread.start();一个是thread.run();和我预计的一样 ...
- vue项目中的字符串每隔4位一个空格
项目中遇到现实银行卡号的需求所以需要这个方法 我们这里运用 JavaScript replace()方法 replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子 ...
- Redis学习之路(二)Redis集群搭建
一.Redis集群搭建说明 基于三台虚拟机部署9个节点,一台虚拟机三个节点,创建出4个master.4个slave的Redis集群. Redis 集群搭建规划,由于集群至少需要6个节点(3主3从模式) ...
- python常用操作和内置函数
一.常用数据处理方法. 1.索引:按照号码将对应位置的数据取出使用 2.list将任意类型数据用逗号分割存在列表中 3.range:产生一堆数字(顾头不顾尾) 4.切片:可以从复制数据的一部分,不影响 ...
- Git之pull,fetch差别
简言之, pull=fetch+merge,下拉远程分支并与本地分支合并. fetch只是下拉远程分支,怎么合并,可以自己再做选择. 进一步了解是,git本地有暂存区(亦称为Index区) fetch ...