核心的类
例子1
服务器端代码
package com.nio.test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.nio.channels.SocketChannel;
public class NIOServer2 {
/*标志数字*/
private static int flag = 0;
/*定义缓冲区大小*/
private static int block = 4096;
/*接收缓冲区*/
private static ByteBuffer receiveBuffer = ByteBuffer.allocate(block);
/*发送缓冲区*/
private static ByteBuffer sendBuffer = ByteBuffer.allocate(block);
/*定义Selector*/
private Selector selector;
public NIOServer2(int port) throws IOException{
//打开服务器套接字通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//服务器配置为非阻塞
serverSocketChannel.configureBlocking(false);
//检索与此服务器套接字通道关联的套接字
ServerSocket serverSocket = serverSocketChannel.socket();
//进行服务的绑定
serverSocket.bind(new InetSocketAddress(port));
//通过open()方法找到Selector
selector = Selector.open();
//注册到selector
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Server Start -----8888:");
}
//监听
public void listen() throws IOException{
while(true){
//监控所有注册的 channel ,当其中有注册的 IO 操作可以进行时,该函数返回,并将对应的 SelectionKey 加入 selected-key set
selector.select();
//Selected-key set 代表了所有通过 select() 方法监测到可以进行 IO 操作的 channel ,这个集合可以通过 selectedKeys() 拿到
Set
Iterator
while(iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
handleKey(selectionKey);
iterator.remove();
}
}
}
//处理请求
public void handleKey(SelectionKey selectionKey) throws IOException{
//接受请求
ServerSocketChannel serverSocketChannel = null;
SocketChannel socketChannel = null;
String receiveText;
String sendText;
int count;
//测试此键的通道是否准备好接受新的套接字连接
if(selectionKey.isAcceptable()){
//返回创建此键的通道
serverSocketChannel = (ServerSocketChannel)selectionKey.channel();
//接受客户端建立连接的请求,并返回 SocketChannel 对象
socketChannel = serverSocketChannel.accept();
//配置为非阻塞
socketChannel.configureBlocking(false);
//注册到selector
socketChannel.register(selector, SelectionKey.OP_READ);
}else if(selectionKey.isReadable()){
//返回为之创建此键的通道
socketChannel = (SocketChannel)selectionKey.channel();
//将缓冲区清空,以备下次读取
receiveBuffer.clear();
//将发送来的数据读取到缓冲区
count = socketChannel.read(receiveBuffer);
if(count>0){
receiveText = new String(receiveBuffer.array(),0,count);
System.out.println("服务器端接受到的数据---"+receiveText);
socketChannel.register(selector, SelectionKey.OP_WRITE);
}
}else if (selectionKey.isWritable()) {
//将缓冲区清空以备下次写入
sendBuffer.clear();
// 返回为之创建此键的通道。
socketChannel = (SocketChannel) selectionKey.channel();
sendText="message from server--" + flag++;
//向缓冲区中输入数据
sendBuffer.put(sendText.getBytes());
//将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
sendBuffer.flip();
//输出到通道
socketChannel.write(sendBuffer);
System.out.println("服务器端向客户端发送数据--:"+sendText);
socketChannel.register(selector, SelectionKey.OP_READ);
}
}
public static void main(String[] args) throws IOException {
int port = 8080;
NIOServer2 server = new NIOServer2(port);
server.listen();
}
}
客户端代码
package com.nio.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.SocketChannel;
import java.util.Set;
public class NIOClient2 {
/*标识数字*/
private static int flag = 0;
/*缓冲区大小*/
private static int BLOCK = 4096;
/*接受数据缓冲区*/
private static ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK);
/*发送数据缓冲区*/
private static ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK);
/*服务器端地址*/
private final static InetSocketAddress SERVER_ADDRESS = new InetSocketAddress(
"localhost", 8888);
public static void main(String[] args) throws IOException {
// 打开socket通道
SocketChannel clientChannel = SocketChannel.open();
// 设置为非阻塞方式
clientChannel.configureBlocking(false);
// 打开选择器
Selector selector = Selector.open();
// 注册连接服务端socket动作
clientChannel.register(selector, SelectionKey.OP_CONNECT);
// 连接
clientChannel.connect(SERVER_ADDRESS);
SocketChannel socketChannel;
Set
String receiveText;
String sendText;
int count=0;
while (true) {
//选择一组键,其相应的通道已为 I/O 操作准备就绪。
//监控所有注册的 channel ,当其中有注册的 IO 操作可以进行时,该函数返回,并将对应的 SelectionKey 加入 selected-key set
selector.select();
//返回此选择器的已选择键集。
selectionKeys = selector.selectedKeys();
//System.out.println(selectionKeys.size());
for(SelectionKey selectionKey:selectionKeys){
//判断是否为建立连接的事件
if (selectionKey.isConnectable()) {
System.out.println("客户端11111111111111111");
System.out.println("client connect");
socketChannel = (SocketChannel) selectionKey.channel(); //
// 判断此通道上是否正在进行连接操作。
// 完成套接字通道的连接过程。
if (socketChannel.isConnectionPending()) {
//完成连接的建立(TCP三次握手)
socketChannel.finishConnect();
System.out.println("完成连接!");
sendBuffer.clear();
sendBuffer.put("Hello,Server".getBytes());
sendBuffer.flip();
socketChannel.write(sendBuffer);
}
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (selectionKey.isReadable()) {
socketChannel = (SocketChannel) selectionKey.channel();
System.out.println("客户端222222222222");
//将缓冲区清空以备下次读取
receiveBuffer.clear();
//读取服务器发送来的数据到缓冲区中
count=socketChannel.read(receiveBuffer);
if(count>0){
receiveText = new String( receiveBuffer.array(),0,count);
System.out.println("客户端接受服务器端数据--:"+receiveText);
socketChannel.register(selector, SelectionKey.OP_WRITE);
}
} else if (selectionKey.isWritable()) {
System.out.println("客户端33333333333333333");
sendBuffer.clear();
socketChannel = (SocketChannel) selectionKey.channel();
sendText = "message from client--" + (flag++);
sendBuffer.put(sendText.getBytes());
//将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
sendBuffer.flip();
socketChannel.write(sendBuffer);
System.out.println("客户端向服务器端发送数据--:"+sendText);
socketChannel.register(selector, SelectionKey.OP_READ);
}
}
selectionKeys.clear();
}
}
}
例子二
服务器端代码:
package com.nio.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.util.Iterator;
public class NioServer1 {
//通道管理器
private Selector selector;
//获取一个ServerSocket通道,并初始化通道
public NioServer1 init(int port) throws IOException{
//获取一个ServerSocket通道
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.socket().bind(new InetSocketAddress("192.168.10.129",port));
//获取通道管理器
selector=Selector.open();
//将通道管理器与通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,
//只有当该事件到达时,Selector.select()会返回,否则一直阻塞。
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
return this;
}
public void listen() throws IOException{
System.out.println("服务器端启动成功");
//使用轮询访问selector
while(true){
//当有注册的事件到达时,方法返回,否则阻塞。
selector.select();
//获取selector中的迭代器,选中项为注册的事件
Iterator
while(ite.hasNext()){
SelectionKey key = ite.next();
//删除已选key,防止重复处理
ite.remove();
//客户端请求连接事件
if(key.isAcceptable()){
ServerSocketChannel server = (ServerSocketChannel)key.channel();
//获得客户端连接通道
SocketChannel channel = server.accept();
channel.configureBlocking(false);
//向客户端发消息
channel.write(ByteBuffer.wrap(new String("我是服务器").getBytes("gbk")));
//在与客户端连接成功后,为客户端通道注册SelectionKey.OP_READ事件。
channel.register(selector, SelectionKey.OP_READ);
System.out.println("客户端请求连接事件");
}else if(key.isReadable()){//有可读数据事件
//获取客户端传输数据可读取消息通道。
SocketChannel channel = (SocketChannel)key.channel();
//创建读取数据缓冲器
ByteBuffer buffer = ByteBuffer.allocate(10);
channel.read(buffer);
byte[] data = buffer.array();
String message = new String(data,"gbk");
System.out.println("receive message from client, size:" + buffer.position() + " msg: " + message);
}
}
}
}
public static void main(String[] args) throws IOException {
new NioServer1().init(8080).listen();
}
}
客户端代码:
package com.nio.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.SocketChannel;
import java.util.Iterator;
public class NioClient1 {
//管道管理器
private Selector selector;
public NioClient1 init(String serverIp, int port) throws IOException{
//获取socket通道
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
//获得通道管理器
selector=Selector.open();
//客户端连接服务器,需要调用channel.finishConnect();才能实际完成连接。
channel.connect(new InetSocketAddress(serverIp, port));
//为该通道注册SelectionKey.OP_CONNECT事件
channel.register(selector, SelectionKey.OP_CONNECT);
return this;
}
public void listen() throws IOException{
System.out.println("客户端启动");
//轮询访问selector
while(true){
//选择注册过的io操作的事件(第一次为SelectionKey.OP_CONNECT)
selector.select();
Iterator
while(ite.hasNext()){
SelectionKey key = ite.next();
//删除已选的key,防止重复处理
ite.remove();
if(key.isConnectable()){
SocketChannel channel=(SocketChannel)key.channel();
//如果正在连接,则完成连接
if(channel.isConnectionPending()){
channel.finishConnect();
}
channel.configureBlocking(false);
//向服务器发送消息
channel.write(ByteBuffer.wrap(new String("我是客户端").getBytes("gbk")));
//连接成功后,注册接收服务器消息的事件
channel.register(selector, SelectionKey.OP_READ);
System.out.println("客户端连接成功");
}else if(key.isReadable()){ //有可读数据事件。
SocketChannel channel = (SocketChannel)key.channel();
ByteBuffer buffer = ByteBuffer.allocate(10);
channel.read(buffer);
byte[] data = buffer.array();
String message = new String(data,"gbk");
System.out.println("recevie message from server:, size:" + buffer.position() + " msg: " + message);
}
}
}
}
public static void main(String[] args) throws IOException {
new NioClient1().init("192.168.10.129", 8080).listen();
}
}