阻塞IO与非阻塞IO

通常情况下的Socket都是阻塞式的, 程序的输入输出都会让当前线程进入阻塞状态, 因此服务器需要为每一个客户端都创建一个线程。

从JAVA1.4开始引入了NIO API, NIO可以实现非阻塞IO, 这样就可以使用一个线程处理所有的客户请求。

基于NIO的非阻塞Socket通信

服务器将用来监听客户端请求的channel注册到selector上,启动一个线程,使用selector的select()获取求情的客户端的channel数量,

当监听到有客户端请求时,就通过SelectionKey返回对应的客户端channel进行通信。

下面是一个非常简单的例子,

服务器端

 package niochat;

 import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
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; public class NServer {
//用于检查所有channel状态的selector
private Selector selector = null;
static final int PORT = 3001;
private Charset charset = Charset.forName("utf-8");
public void init() throws IOException, InterruptedException {
selector = Selector.open();
//通过open方法打开一个未绑定的ServerSocketChannel实例
ServerSocketChannel server = ServerSocketChannel.open();
InetSocketAddress isa = new InetSocketAddress("127.0.0.1", PORT);
server.bind(isa);
//设置非阻塞
server.configureBlocking(false);
//注册ServerSocketChannel到selector
server.register(selector, SelectionKey.OP_ACCEPT); //服务器端需要轮询selector看是否有channel需要通信
while ( true ) {
//select()将会一直阻塞,直到选择了至少一个channel(进行通信),此时sector就会调用wakeup(),select()方法才能返回
int num = selector.select();
Thread.sleep(1000);
//select()方法返回后,用selectedKeys()返回对应channel的SelectionKey集合,通过key.channel()方法可以返回对应的channel实例
//被选中的key集合selectedKeys表示需要进行IO处理的channel集合,一个key代表一个channel
System.out.println("SelectionKey.size = "+selector.selectedKeys().size());
for (SelectionKey sk : selector.selectedKeys()) {
//从selector上的已选择的key集合中删除正在处理的key
System.out.println("SelectionKey.value = "+sk);
selector.selectedKeys().remove(sk);
//如果sk对应channel包含客户端连接请求
if (sk.isAcceptable()) {
//调用accept方法接受请求,产生一个服务器端的SocketChannel
//在非阻塞模式下,如果没有连接则直接返回null
SocketChannel sc = server.accept();
//设置非阻塞模式
sc.configureBlocking(false);
//将SocketChannel也注册到selector
sc.register(selector, SelectionKey.OP_READ);
//再将sk对应的channel设置为请求准备接受其他请求
sk.interestOps(SelectionKey.OP_ACCEPT);
} //如果sk对应的channel有数据需要读取
if (sk.isReadable()) {
//获取sk对应的channel
SocketChannel sc = (SocketChannel)sk.channel();
//channel中的数据必须先写入buffer中,然后才能写入进content中
ByteBuffer buff = ByteBuffer.allocate(1024);
String content = "";
try {
while(sc.read(buff) > 0) {
//buffer 复位
buff.flip();
content += charset.decode(buff);
}
System.out.println("读取的数据:"+ content);
//sk复位
sk.interestOps(SelectionKey.OP_READ);
} //遇到channel有异常说明客户端有异常,取消注册此sk
catch (IOException ex) {
//从已选择key集合中取消sk,下一次select()时此channel将自动被删除
ex.printStackTrace(); sk.cancel();
if(sk.channel() != null) {
sk.channel().close();
} } if (content.length() > 0) {
//广播
for(SelectionKey key : selector.keys()) {
Channel targetChannel = key.channel();
if (targetChannel instanceof SocketChannel) {
SocketChannel dest = (SocketChannel)targetChannel;
dest.write(charset.encode(content));
}
}
}
} }
}
} public static void main(String[] args) throws IOException, InterruptedException {
new NServer().init();
}
}

客户端

 package niochat;

 import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Scanner; public class NClient {
//定义检测SocketChannel的selector
private Selector selector = null;
private static final int PORT = 3001;
private Charset charset = Charset.forName("utf-8");
//客户端的SocketChannel
private SocketChannel sc = null;
public void init() throws IOException {
selector = Selector.open();
InetSocketAddress isa = new InetSocketAddress("127.0.0.1", PORT);
//调用open静态方法创建连接到指定主机的SocketChannel
sc = SocketChannel.open(isa);
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
//创建子线程读取服务器返回的数据
new ClientThread().start();
//键盘输入流
Scanner scan = new Scanner(System.in);
while (scan.hasNextLine()) {
String line = scan.nextLine();
//放进SocketChannel
sc.write(charset.encode(line));
}
} private class ClientThread extends Thread {
public void run() {
try {
while (selector.select() > 0) {
//被选中的key集合selectedKeys表示需要进行IO处理的channel集合
for (SelectionKey sk : selector.selectedKeys()) {
//删除正在处理的key
selector.selectedKeys().remove(sk);
if (sk.isReadable()) {
SocketChannel sc = (SocketChannel)sk.channel();
ByteBuffer buff = ByteBuffer.allocate(1024);
String content = "";
while (sc.read(buff) > 0) {
sc.read(buff);
buff.flip();
content += charset.decode(buff);
}
System.out.println("聊天信息:"+content);
sk.interestOps(SelectionKey.OP_READ);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) throws IOException {
new NClient().init();
}
}

执行结果,启动了一个服务器端,然后启动了两个客户端,

aaarticlea/png;base64,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urVdFTupLQMApoS/n519Vh+21El28MX2ylEsQ5L6ry0DAMaOv5+9OhyQ9pjMtlQqo6cshzNmqtJ/th/7TAEAI8Lfzx4tMhUAcAh/P3ts5jovAEBf/P1sAACmoe3fzwYAAFZkNgAA00BmAwAwDWQ2AADTQGYDADANZDYAANNAZgMAMA1kNgAA00BmAwAwDWQ2AADTQGYDADANZDYAANNAZgMAMA1kNgAA00BmAwAwDWQ2AADTQGYDADANZDYAANNAZgMAMA1kNgAA00BmAwAwDWQ2AADTQGYDADANZDYAANNAZgMAMA1kNgAA00BmAwAwDWQ2AADTQGYDADANZDYAANNAZgMAMA1kNgAA00BmAwAwDWQ2AADTQGYDADANZDYAANNAZgMAMA1k9hK468vGxsY2g631DbWpDZm9AO4qA8AMtL6hNkVmL0F4ldnY2NgmvbW+oTa1IbMXYENms7GxzWVrfUNtakNmL0B4lf/PQ9/Sc/uLh73lLx72Vrfd4+FvvcfD33aPh7/tHv/0tr882N7+l494+1+57ZGX/LXfHnXp37jt0Zf+zaMvveejL7vnoy+752Muu+djLrvXY95xr8e+416Pfcffuu20y//2tMvvfdrl9z798nuffsW9T7/iPqdfcZ8zrrjPGe+8zxnv/Lsz3vl3j3Pbu/7+8QfbfR//7vs+4WC73xPffb8nvsdt93/Se+7/pPfe/0nvvf+Z733Ame99wJlXPuDMK//vk09tT/nv/+e3f37fA9321Pc98Knv/we3Pe39D3ra+x/0tA886GkfeNDTP/Dgp3/gwU+/6sFnXfXgs676R7c94+p/fMbVD3nG1Q955tUPeeaRhzzzyEOfeeShZx956NnXPOzsax72rIPt4c+69uHPPtj+6TnX+e0Rz73uEc/94COe+8FHPs9tH3rk8z70qH9x24cf9fwPP9pv//qRx5zaHvtv1x9s51x/2jnXn3bO0dPOOXrauUdPP/fo6efecPoLbjj9BTec8YIbznjBjWe88MYzXnjj41544+NedOPjXvTRx7vtxR99/Is/9oQXf+wJL3HbsSe+5NgTX3qwPellx9125suOn/nym9z25Jff9OTzbnryeTc/+bybn/IKt93ylFfc8s+vdNvHn/rvf96e9h+fONhe9Ymnv+qTB9v5nzzr/E+edf6nznr1p8569aee8epPPePV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" alt="" />

JAVA基础知识之网络编程——-基于NIO的非阻塞Socket通信的更多相关文章

  1. JAVA基础知识之网络编程——-基于UDP协议的通信例子

    UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramS ...

  2. JAVA基础知识之网络编程——-基于AIO的异步Socket通信

    异步IO 下面摘子李刚的<疯狂JAVA讲义> 按照POSIX标准来划分IO,分为同步IO和异步IO.对于IO操作分为两步,1)程序发出IO请求. 2)完成实际的IO操作. 阻塞IO和非阻塞 ...

  3. JAVA基础知识之网络编程——-基于TCP通信的简单聊天室

    下面将基于TCP协议用JAVA写一个非常简单的聊天室程序, 聊天室具有以下功能, 在服务器端,可以接受客户端注册(用户名),可以显示注册成功的账户 在客户端,可以注册一个账号,并用这个账号发送信息 发 ...

  4. JAVA基础知识之网络编程——-网络基础(Java的http get和post请求,多线程下载)

    本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web ...

  5. JAVA基础知识之网络编程——-网络通信模型(IO模型)

    <Unix网络编程:卷1>中介绍了5中I/O模型,JAVA作为运行在宿主机上的程序,底层也遵循这5中I/O模型规则.这5中I/O模型分别是: 阻塞式IO 非阻塞式IO I/O复用 信号驱动 ...

  6. JAVA基础知识之网络编程——-TCP/IP协议,socket通信,服务器客户端通信demo

    OSI模型分层 OSI模型是指国际标准化组织(ISO)提出的开放系统互连参考模型(Open System Interconnection Reference Model,OSI/RM),它将网络分为七 ...

  7. java nio实现非阻塞Socket通信实例

    服务器 package com.java.xiong.Net17; import java.io.IOException; import java.net.InetSocketAddress; imp ...

  8. JAVA基础知识之网络编程——-使用Proxy创建连接

    在前面的HTTP网络通信的例子中,使用了URLConnection conn = url.openConnection();连接网络, 如果改用URLConnection conn = url.ope ...

  9. JAVA基础知识之网络编程——-使用MutilcastSocket实现多点广播

    IP多点广播原理 设置一组特殊网络地址作为多点广播地址,每一个多点广播地址都被看作一个组,当客户需要发送和接受信息时,加入到该组即可. IP协议为多点广播提供了一批特殊的IP地址,范围是224.0.0 ...

随机推荐

  1. linux 内核模块ko入门

    http://blog.csdn.net/elfylin/article/details/5908265

  2. Java基础(5):试用Array类对数据进行操作(Sort和toString方法)

    Arrays 类是 Java 中提供的一个工具类,在 java.util 包中.该类中包含了一些方法用来直接操作数组,比如可直接实现数组的排序.搜索等 1. 排序 语法:  Arrays.sort(数 ...

  3. C#: 集合

    摘自http://www.cnblogs.com/kissdodog/archive/2013/01/29/2882195.html 先来了解下集合的基本信息 1.BCL中集合类型分为泛型集合与非泛型 ...

  4. android adb shell

    http://blog.csdn.net/zyp009/article/details/8332925 最快的Android模拟器Genymotion的安装与使用 http://blog.csdn.n ...

  5. PAT乙级 1011. A+B和C (15)

    1011. A+B和C (15) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 HOU, Qiming 给定区间[-231, 231 ...

  6. React组件开发

    目录: 属性:props 内联样式 状态记忆 : state 生命周期 访问DOM 表单输入 承接快速入门篇:http://www.cnblogs.com/jasonnode/p/4444504.ht ...

  7. NOIP200504循环

    NOIP200504循环 乐乐是一个聪明而又勤奋好学的孩子.他总喜欢探求事物的规律.一天,他突然对数的正整数次幂产生了兴趣.众所周知,2的正整数次幂最后一位数总是不断的在重复2,4,8,6,2,4,8 ...

  8. 【GDI+】 线段 文字 定位的问题

    遇到一个看起来很简单的问题: 给定两个点,和一组文字,希望文字显示在线的附近并且居中显示.期望像这样的效果 进一步的抽象是: 1.根据文字的长度和高度,以及两个点,来获得文字的定位点(左上角点)的 2 ...

  9. HashMap存值

    package com.exmple.tool; import java.util.HashMap; public class UserTool { public static HashMap< ...

  10. jquery中的each用法以及js中的each方法实现实例

    each()方法能使DOM循环结构简洁,不容易出错.each()函数封装了十分强大的遍历功能,使用也很方便,它可以遍历一维数组.多维数组.DOM, JSON 等等在javaScript开发过程中使用$ ...