161111、NioSocket的用法(new IO)
今天先介绍NioSocket的基本用法,实际使用一般会采用多线程,后面会介绍多线程的处理方法。
从jdk1.4开始,java增加了新的io模式--nio(new IO),nio在底层采用了新的处理方式,极大地提高了IO效率。我们使用的Socket也属于IO的一种,nio提供了相应的工具:ServerSocketChanner和SocketChannel,它们分别对应ServerSocket和Socket。(不了解java socket可以百度下)
NioSocket包括三个重要的概念:Buffer(类似于送快递中的货物)、Channel(类似于送快递中的送货车)和Selector(类似于送快递中转站的分拣员)。原来的Socket类似于一个人送快递,没有形成产业链。
下面来看下代码:
服务端
package com.test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
public class NIOServer {
public static void main(String[] args) throws Exception {
//创建ServerSocketChannel,监听8080端口
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(8080));
//设置为非阻塞模式
ssc.configureBlocking(false);
//为ServerSocketChannel注册选择器
Selector selector = Selector.open();
/**
* 这里有四种SelectionKey分别表示接受请求操作、链接操作、读操作和写操作
* SelectionKey.OP_ACCEPT
* SelectionKey.OP_CONNECT
* SelectionKey.OP_READ
* SelectionKey.OP_WRITE
*/
ssc.register(selector, SelectionKey.OP_ACCEPT);
//创建处理器
Handler handler = new Handler(1024);//handler的创建在下面静态的内部类中
while(true){
//等待请求,每次等待阻塞3s,超过3s后线程继续向下运动,如果传入0或者不传入参数将一直阻塞
if(selector.select(3000) == 0){
System.out.println("等待请求超时....");
continue;
}
System.out.println("处理请求......");
//获取待处理的SelectionKey
Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();
while(keyIter.hasNext()){
SelectionKey key = keyIter.next();
try {
//接收到链接请求时
if(key.isAcceptable()){
handler.handAccept(key);//改变Selector为读操作
}
//读数据
if(key.isReadable()){
handler.handlerRead(key);
}
} catch (Exception e) {
keyIter.remove();
continue;
}
//处理完成后,从待处理的SelectionKey迭代器中移除当前所使用的key
keyIter.remove();
}
}
}
public 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 handAccept(SelectionKey key) throws IOException {
SocketChannel sc = ((ServerSocketChannel)key.channel()).accept();
sc.configureBlocking(false);
sc.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize));//改变Selector为读操作
}
public void handlerRead(SelectionKey key) throws IOException {
//获取channel
SocketChannel sc = (SocketChannel) key.channel();
//获取channel并重置
ByteBuffer buffer = (ByteBuffer) key.attachment();
buffer.clear();
//没有读到内容则关闭
if(sc.read(buffer)==-1){
sc.close();
}else{
//将buffer转成读状态
buffer.flip();
//将buffer中接收到的值按localCharset格式编码后保存到receivedString
String receivedString = Charset.forName(localCharset).newDecoder().decode(buffer).toString();
System.out.println("received from client: " + receivedString);
//返回数据给客户端
String sendString = "received data: " + receivedString;
buffer = ByteBuffer.wrap(sendString.getBytes(localCharset));
sc.write(buffer);
//关闭socket
sc.close();
}
}
}
}
161111、NioSocket的用法(new IO)的更多相关文章
- Java中的Socket的用法
Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...
- 第一篇 网站基础知识 第4章 Java中Socket的用法
第4章 Java中Socket的用法 4.1 普通Socket的用法 Java中的网络通信是通过Socket实现的,Socket分为ServetSocket和Socket两大类,ServetSocke ...
- Java中的Socket用法
转发链接:https://www.cnblogs.com/zhanglei93/p/6217384.html (1)Java中的Socket用法 Java中的Socket分为普通的Socket和Nio ...
- 利用socket.io实现消息实时推送
最近在写的项目中存在着社交模块,需要实现这样的一个功能:当发生了用户被点赞.评论.关注等操作时,需要由服务器向用户实时地推送一条消息.最终完成的项目地址为:socket-message-push,这里 ...
- 高级Java工程师必备 ----- 深入分析 Java IO (三)
概述 Java IO即Java 输入输出系统.不管我们编写何种应用,都难免和各种输入输出相关的媒介打交道,其实和媒介进行IO的过程是十分复杂的,这要考虑的因素特别多,比如我们要考虑和哪种媒介进行IO( ...
- Java之io nio aio 的区别
这个问题最近面试总是遇到,作为一个只会写流水代码的程序员,一脸懵逼.看了网上的解释,看的还是很模糊,说下我对这个的理解. 先引出一个话题,两个大水缸,一个空一个满,让你把一个缸里面的水弄到另一个里面. ...
- 转: 从Mysql某一表中随机读取n条数据的SQL查询语句
若要在i ≤ R ≤ j 这个范围得到一个随机整数R ,需要用到表达式 FLOOR(i + RAND() * (j – i + 1)).例如, 若要在7 到 12 的范围(包括7和12)内得到一个随机 ...
- .net(C#)操作文件的几种方法汇总
.net(C#)操作文件的几种方法汇总 System.IO命名空间下类的用法:在System.IO名称空间中包含了用于文件输入输出的主要类.File:实用类,提供许多静态方法,用于移动.复制和删除文件 ...
- 【MySQL性能优化】改进MySQL Order By Rand()的低效率
<a href="http://click.aliyun.com/m/9153/">点击查看原文</a> 正 文: 最近由于需要研究了一下MYSQL的随 ...
随机推荐
- Inside Kolla - 04 Kolla 目录结构
Kolla 目录结构 把 Kolla 的源代码下载下来后,先从总体上分析 Kolla 的目录结构,查看顶层目录结构,使用 tree -L 1 输出 . ├── ansible ├── compose ...
- AsyncTask的使用方法和理解
.对于耗时的操作,我们的一般方法是开启“子线程”.如果需要更新UI,则需要使用handler 2.如果耗时的操作太多,那么我们需要开启太多的子线程,这就会给系统带来巨大的负担,随之也会带来性能方面的问 ...
- PHP编码规范(转)
一.文件格式 1. 对于只含有 php 代码的文件,我们将在文件结尾处忽略掉 "?>" .这是为了防止多余的空格或者其它字符影响到代码.例如:<?php$foo = ' ...
- cookie&session&servletContext
一.cookie VS session 1)应用场景 cookie可以用于: 记录用户上次登录的时间 记住用户名和密码 session可以用于: 防止非法登录(即直接跳转到本来需登录验证方可登录的页面 ...
- 记32位程序(使用3gb用户虚拟内存)使用D3DX9导致的一个崩溃的问题
为了增加32位程序的用户虚拟内存的使用量,我们使用了/LARGEADDRESSAWARE编译选项来使32位程序可能使用到3gb的内存,能否使用到3gb内存也跟平台.系统和设置有关系,现摘抄部分作为参考 ...
- ORA-19693: 已包括备份片段
使用rman异机恢复数据时,报"ORA-19693: 已包括备份片段..."错误. 执行的rman命令: RMAN> run{ 2> allocate channel ...
- 使用duplicate target database ... from active database复制数据库
使用duplicate target database ... from active database复制数据库 source db:ora11auxiliary db:dupdb 1.修改监听文件 ...
- SQL百分比
百分比=cast(cast(count(ProvinceName)*100./ (select count(Id) from dbo.TopicCurrent where boardId=316 ...
- 转:Python一些特殊用法(map、reduce、filter、lambda、列表推导式等)
Map函数: 原型:map(function, sequence),作用是将一个列表映射到另一个列表, 使用方法: def f(x): return x**2 l = range(1,10) map( ...
- Java之Structs框架初探
今天是小白第一次自己的接触Struts框架,因为网上的资料都是从Structs2开始,跟Structs1完全不同,因此,小白直接跳过1学习版本2的搭建,废话不多说,直接开始. 首先要搭建框架,就肯定要 ...