JAVA nio 简单使用
nio 模拟客户端和服务器互相通讯--传输一个int值,并且不断的+1;
服务器,单线程
public class Server {
public static void main(String[] args) {
try {
ServerSocketChannel server=ServerSocketChannel.open().bind(new InetSocketAddress(8881));
server.configureBlocking(false);
Selector selector=Selector.open();
server.register(selector,SelectionKey.OP_ACCEPT);
for(;;) {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while(iterator.hasNext()) {
SelectionKey next = iterator.next();
if(next.isAcceptable()) {
acceptHandle(next, selector);
}
if (next.isReadable()) {
doRead(next, selector);
}
iterator.remove();
}
Thread.sleep(2000);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void acceptHandle(SelectionKey key,Selector selector) throws IOException {
ServerSocketChannel serverShannel =(ServerSocketChannel) key.channel();
SocketChannel channel = serverShannel.accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ,ByteBuffer.allocate(1024));
}
public static void doRead(SelectionKey key,Selector selector) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer =(ByteBuffer) key.attachment();
buffer.clear();
int read = socketChannel.read(buffer);
int msg=buffer.getInt(0);
System.out.println("服务器收到客户端"+socketChannel.getLocalAddress()+" "+msg);
buffer.rewind();
buffer.putInt(msg+1);
buffer.flip();
socketChannel.write(buffer);
//buffer.clear();
}
}
服务器,多线程
public class Server {
private static ExecutorService executorService = Executors.newFixedThreadPool(4);//指定线程数大小
public static void main(String[] args) {
try {
ServerSocketChannel server=ServerSocketChannel.open().bind(new InetSocketAddress(8881));
server.configureBlocking(false);
Selector selector=Selector.open();
server.register(selector,SelectionKey.OP_ACCEPT);
for(;;) {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while(iterator.hasNext()) {
SelectionKey next = iterator.next();
if(next.isAcceptable()) {
acceptHandle(next, selector);
}
if (next.isReadable()) {
executorService.submit(new Runnable() {//调用多线程,,这样子的话就是 accept 一个线程,read,write一个线程
@Override
public void run() {
// TODO Auto-generated method stub
try {
doRead(next, selector);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
iterator.remove();
}
Thread.sleep(2000);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void acceptHandle(SelectionKey key,Selector selector) throws IOException {
ServerSocketChannel serverShannel =(ServerSocketChannel) key.channel();
SocketChannel channel = serverShannel.accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ,ByteBuffer.allocate(1024));
}
public static void doRead(SelectionKey key,Selector selector) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer =(ByteBuffer) key.attachment();
buffer.clear();
int read = socketChannel.read(buffer);
int msg=buffer.getInt(0);
System.out.println(Thread.currentThread().getName()+" 服务器收到客户端"+socketChannel.getLocalAddress()+" "+msg);
buffer.rewind();
buffer.putInt(msg+1);
buffer.flip();
socketChannel.write(buffer);
//buffer.clear();
}
}
客户端
public class Client {
public static void main(String[] args) {
try(SocketChannel channel=SocketChannel.open();
Selector selector=Selector.open();
) {
channel.configureBlocking(false);
if(!channel.connect(new InetSocketAddress("127.0.0.1", 8881))) {
while(!channel.finishConnect()) {};
System.out.println("连接到服务器");
}
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.putInt(1);
buffer.flip();
channel.write(buffer);
channel.register(selector, SelectionKey.OP_READ,buffer);
for(;;) {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while(iterator.hasNext()) {
SelectionKey next = iterator.next();
if(next.isReadable()) {
doRead(next,selector);
}
iterator.remove();
}
Thread.sleep(2000);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void doRead(SelectionKey key,Selector selector) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer =(ByteBuffer) key.attachment();
buffer.clear();
socketChannel.read(buffer);
int msg=buffer.getInt(0);
System.out.println("客户端收到服务器返回的信息"+socketChannel.getLocalAddress()+" "+msg);
buffer.putInt(0,msg+1);
buffer.flip();
socketChannel.write(buffer);
}
}
**ByteBuffer 是一个缓存区,用来保存用户要传输的数据,里面的读写方法是有一个 position ,limiet , capacity。 + position类似一个指针,可以理解为记事本里的光标。代表了一个位置 + limit是指针位置的最大限制, + capacity指的是容量 就是ByteBuffer的大小。 ByteBuffer 几个方法 clear(), flip(),rewind()等,都是对上面3个值进行操作。 而调用ChannelSocket的read() ,write()方法,传入一个ByteBuffer。都是根据传入的ByteBuffer里的3个值,进行读写。 例如: ``` ByteBuffer buf=new ByteBuffer(1024); //position=0,limit=1024,capacity=1024 buf.putInt(1);//在position为0的位置放入一个int,int为4字节,放完后。position=4; channel.write(buf);//这里socket去传输这个buffer,这里也是从position=4的地方开始写的,一直写到limit。然后相当于没传数据 ```