NIO编程

来源:互联网 发布:淘宝号出租平台 编辑:程序博客网 时间:2024/05/17 06:24
public class Server implements Runnable{
//1多路复用器(管理所有同道)
private Selector selector;
//2建立缓冲区
private ByteBuffer readBuf = ByteBuffer.allocate(1024);
//3
private ByteBuffer writeBuf = ByteBuffer.allocate(1024);

public Server(int port){
try{
//1打开路复用器
this.selector = Selector.open();
//2打服务器道
ServerSocketChannel ssc = ServerSocketChannel.open();
//3设置复用器通道为非阻塞模式
ssc.configureBlocking(false);
//4绑定地址
ssc.bind(new InetSocketAddress(port));
//5把服务器通道注册到多路复用器上,并监听阻塞事件
ssc.register(this.selector, SelectionKey.OP_ACCEPT);
System.out.println("Server start,port:"+port);
}catch(Exception e){
e.printStackTrace();
}
}

@Override
public void run() {
while(true){
try{
//1 必须让多路复用器开始监听
this.selector.select();
//2返回多路复用器已选择的结果集
Iterator<SelectionKey> keys = this.selector.selectedKeys().iterator();
//3进行遍历
while(keys.hasNext()){
//4获取一个元素
SelectionKey key = keys.next();
//5直接从容器中移除就可以了
keys.remove();
//6如果是有效的
if(key.isValid()){
//7如果为阻塞状态
if(key.isAcceptable()){
this.accept(key);
}
//8如果为可读状态
if(key.isReadable()){
this.read(key);
}
//写数据
if(key.isWritable()){
this.write(key);
}
}
}
}catch(IOException e){
e.printStackTrace();
}
}
}


public void read(SelectionKey key){
try{
//1清空缓冲区旧的数据
this.readBuf.clear();
//2获取之前注册的socket通道对象
SocketChannel sc = (SocketChannel) key.channel();
//3读取数据
int count = sc.read(this.readBuf);
//4如果没有数据
if(count == -1){
key.channel().close();
key.cancel();return;
}
//5有数据进行读取 读取之前需要进行复位方法(把posion和limit进行复位)
this.readBuf.flip();
//6根据缓冲区的数据长度创建相应大小的byte数组,接收缓冲区的数据
byte[] bytes = new byte[this.readBuf.remaining()];
//7接受缓冲区数据
this.readBuf.get(bytes);
//8打印结果
String body = new String(bytes).trim();
System.out.println("Server : " + body);
//9可以写回给客户端数据

}catch(Exception e){
e.printStackTrace();
}
}

public void write(SelectionKey key){
//ServerSocketChannel ssc =  (ServerSocketChannel) key.channel();
//ssc.register(this.seletor, SelectionKey.OP_WRITE);
}

public void accept(SelectionKey key){
try{
//1 获取服务通道
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
//2执行阻塞方法
SocketChannel sc = ssc.accept();
//3设置阻塞模式 为非阻塞
sc.configureBlocking(false);
//4注册到多路复用器上,并设置读取顺序
sc.register(this.selector, SelectionKey.OP_READ);

}catch(IOException e){
e.printStackTrace();
}
}

public static void main(String[] args) {
new Thread(new Server(8765)).start();
}

}


public class Client {



public static void main(String[] args) {
//创建连接地址
InetSocketAddress address = new InetSocketAddress("127.0.0.1",8765);

//声明连接通道
SocketChannel sc = null;

ByteBuffer buf = ByteBuffer.allocate(1024);

try{
sc = SocketChannel.open();
sc.connect(address);//建立连接 注册到selector

while(true){
byte[] bytes = new byte[1024];
System.in.read(bytes);

buf.put(bytes);
buf.flip();
sc.write(buf);
buf.clear();
}
}catch(IOException e){
e.printStackTrace();
}finally{
if(sc != null){
try {
sc.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}
}

原创粉丝点击