package NonBlockingSocket;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
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 Server {// 这是服务端
/**
* @param args
* @throws IOException
*
* 非阻塞的Socked使用总结(服务器端): 一、涉及关键类: 1、ByteBuffer 2、SelectionKey 3、Selector
* 4、ServerSocketChannel 5、Iterator 6、SocketChannel 二、各类的综合使用方法及相互联系
* 以下是使用前对各对象的设置: 1、得到ServerSocketChannel和Selector对象
* 2、设置ServerSocketChannel内部channel阻塞方式 3、把ServerSocketChannel绑定到指定地址的指定端口上
* 4、把ServerSocketChannel注册给Selector对象,并选择感兴趣的动作 以下是使用过程:
* 1、使用Selector对象对指定地址指定端口的请求进行选择,这里的选择只关注自己以前设置的感兴趣的请求
* 2、从Selector对象里得到感兴趣的链接的Set,然后得到该Set对象的迭代器Iterator对象
* 3、如果该迭代器里有元素,则依次使用next()取出,取出的元素可强转为SelectionKey,此SelectionKey对象至少包装了两个属性:一个是该属性是哪种类型的,另一个是一个SelectableChannel
* 如果此SelectedKey是OP_ACCEPT,那么SelectableChannel可以强转为ServerSocketChannel对象,使这个对象accept()可以得到SocketChannel对象,同样可以像注册ServerSocketChannel
* 一样注册SocketChannel到Selector对像并选择自己感兴趣的动作。SelectionKey的isConnecttable()方法不适用于服务端。
* 4、可以从SocketChannel内read()和write()信息,这些信息必须包装在ByteBuffer内
* 5、可以对ByteBuffer里的内容做多种解释,其中一种是人类比较容易理解的字符格式:CharBuffer,转换方式有两种:一种是ByteBuffer.asCharBuffer()这种转换只是改变了相同内容的不同解释;
* 另一种是使用编码: Charset tCs=Charset.forName("gb2312"); CharBuffer
* tCb=tCs.newDecoder().decode(tBb); 这种转换是对相同语义做不同存储。
* 6、经常将上述步骤放在一个大的循环内部,这样可以不断地检查指定地址的指定端口的请求
*/
private final static int BUF_SIZE = 1024;
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Server s = new Server();
s.startServer();
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//
public Server() {
// TODO Auto-generated constructor stub
init();
}
ServerSocketChannel ssc;
Selector sel;
boolean start;
//
private void init() {
// TODO Auto-generated method stub
try {
ssc = ServerSocketChannel.open();
ssc.socket()
.bind(
new InetSocketAddress(InetAddress
.getByAddress(new byte[] { (byte) 11,
(byte) 11, (byte) 11, (byte) 11 }),
1111));
sel = Selector.open();
ssc.configureBlocking(false);
ssc.register(sel, SelectionKey.OP_ACCEPT);
start = false;
aid = 0;
rid = 0;
wid = 0;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static int rid;
private static int wid;
private static int aid;
//
private void startServer() throws IOException {
// TODO Auto-generated method stub
start = true;
Iterator<SelectionKey> iKey = null;
SelectionKey skKey = null;
System.out.println("Server started.");
while (start) {
sel.select();// 不要忘了
iKey = sel.selectedKeys().iterator();
if (iKey.hasNext()) {
// System.out.println("Server=====>>>hasNext");
skKey = iKey.next();
iKey.remove();
if (skKey.isAcceptable()) {
aid++;
ServerSocketChannel tSsc = (ServerSocketChannel) skKey
.channel();
SocketChannel tSc = tSsc.accept();
tSc.configureBlocking(false);
tSc.register(sel, SelectionKey.OP_READ
| SelectionKey.OP_WRITE);
System.out.println("The " + aid + "th accept.");
continue;
}
if (skKey.isReadable()) {
rid++;
SocketChannel tSc = (SocketChannel) skKey.channel();
tSc.configureBlocking(false);
// ByteBuffer的创建方法之一:ByteBuffer.allocate(BUF_SIZE);
ByteBuffer tBb = ByteBuffer.allocate(BUF_SIZE);
tSc.read(tBb);
tBb.flip();
// 以下做解码用:
Charset tCs = Charset.forName("gb2312");
CharBuffer tCb = tCs.newDecoder().decode(tBb);
System.out.println(tCb);
System.out.println("The " + rid + "th read.");
continue;
}
if (skKey.isWritable()) {
wid++;
SocketChannel tSc = (SocketChannel) skKey.channel();
tSc.configureBlocking(false);
// CharBuffer tCb=ByteBuffer.wrap(("The "+wid+"th
// response.").getBytes()).asCharBuffer();
// ByteBuffer的创建方法之二:ByteBuffer.wrap(("The "+wid+"th
// response.").getBytes())
tSc.write(ByteBuffer.wrap(("The " + wid + "th response.")
.getBytes()));
System.out.println("The " + wid + "th write.");
continue;
}
}
}
}
}
分享到:
相关推荐
可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件...
第一章 概论 .................................................................................................................. 1 1.1 网络的历史...........................................................
7.2 非阻塞式i/o 7.2.1 读操作 7.2.2 写操作 7.2.3 建立连接过程 7.2.4 接收连接过程 7.2.5 非阻塞方式的实现 7.3 实例 7.3.1 taik实例 7.3.2 可处理并发服务的echo实例 第8章 套接字属性控制 ...
9.2 poll系统调用 9.3 epoll系列系统调用 9.3.1 内核事件表 9.3.2 epoll_wait函数 9.3.3 LT和ET模式 9.3.4 EPOLLONESHOT事件 9.4 三组IO复用函数的比较 9.5 IO复用的高级应用一:非阻塞connect 9.6 IO复用...
14.2.4.2 非阻塞I/O.98 14.2.4.3 缓冲 ..98 参考文献. 100 例索引 例 1-1 输出一段字符串的例子.. 2 例 1-2 source命令的简单例子 3 例 2-1 输出一个词的例子 5 例 2-2 参数定义、赋值与参数值引用 5 例 2-3...
257 13.4.2 准备状态 257 13.4.3 运行状态 257 13.4.4 等待/阻塞状态 258 13.4.5 死亡状态 258 13.5 线程的调度 258 13.5.1 睡眠方法 258 13.5.2 线程优先级 260 13.5.3 yield让步方法 261 13.5.4 join让步方法 262 ...
6.10.2 非阻塞模式I/O.... 180 6.10.3 I/O 多路复用.... 181 6.10.4 信号驱动I/O 模式........... 182 6.10.5 异步I/O 模式... 185 6.10.6 几种I/O 模式的比较........ 186 6.10.7 fcntl()函数........ 186 6.10.8 ...
4.6.6 数组的应用举例 103 4.7 本章小结 106 本章练习 106 第5章 面向对象(上) 107 5.1 类和对象 108 5.1.1 定义类 108 学生提问:构造器不是没有返回值吗?为什么不能用void修饰呢? 110 5.1.2 对象的产生...
3.3 数学运算举例.........................................................................................................................9 3.4 INCR命令....................................................
第一章 概论 ..................................................................................................................1 1.1 网络的历史.............................................................
使用socket建立客户端与服务器的通信的过程 60.JAVA语言国际化应用,Locale类,Unicode 61.描述反射机制的作用 62.如何读写一个文件? 63.在图形界面中,一个按钮如何处理鼠标点击事件? 64.在图形界面中,一个...