Java网络编程-Nio 实例代码

时间:2021-04-16 20:14:38


  IO NIO 区别请看 : http://blog.csdn.net/jiangtao_st/article/details/38041479


一、基于Nio的 Server ,过程略复杂,但是无疑这样的效率高;代码中得注释比较详细,请看注释说明

package com.zhuoxuan.net.nio;

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.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;

/**
*
* <p>
* 基于nio的Server
* </p>
*
* @author 卓轩
* @创建时间:2014年7月7日
* @version: V1.0
*/
public class NioServer {

private final int port = 8787;
private final int BLOCK_SIZE = 4096;

private Selector selector;

private ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK_SIZE);
private ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK_SIZE);




//构造函数
public NioServer() throws IOException {
//打开服务器套接字通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//服务器配置为非阻塞模式
serverSocketChannel.configureBlocking(false);
//获取与通道关联的 ServerSocket对象
ServerSocket serverSocket = serverSocketChannel.socket();
//绑定端口
serverSocket.bind(new InetSocketAddress(port));
//打开一个选择器
selector = Selector.open();
//注册到selector上,等待连接
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

System.out.println("Server:init successfuly.");
}

/**
* 监听端口
*/
private void linstenr() throws Exception{

while (true) {
//选择一组键
selector.select();
//返回获取选择的键集
Set<SelectionKey> selectionKeys = selector.selectedKeys();
if(selectionKeys.isEmpty()){
continue;
}
//遍历,循环处理请求的键集
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = (SelectionKey) iterator.next();
iterator.remove();
handlerKey(selectionKey);
}

Thread.sleep(4000);
}

}

/**
* 处理对应的 SelectionKey
* @param selectionKey
*/
private void handlerKey(SelectionKey selectionKey) throws IOException{

ServerSocketChannel server;
SocketChannel client;

// 测试此键的通道是否已准备好接受新的套接字连接
if(selectionKey.isAcceptable()){
//此键对应的关联通道
server = (ServerSocketChannel)selectionKey.channel();
//接受到此通道套接字的连接
client = server.accept();
//配置为非阻塞
client.configureBlocking(false);
//注册到selector 等待连接
client.register(selector, SelectionKey.OP_READ);

}

else if (selectionKey.isReadable()) {

client = (SocketChannel)selectionKey.channel();
//将缓冲区清空,下面读取
receiveBuffer.clear();
//将客户端发送来的数据读取到 buffer中
int count = client.read(receiveBuffer);
if(count >0){
String receiveMessage = new String(receiveBuffer.array(),0,count);
System.out.println("Server:接受客户端的数据:" + receiveMessage);
client.register(selector, SelectionKey.OP_WRITE);
}
}

else if (selectionKey.isWritable()) {
//发送消息buffer 清空
sendBuffer.clear();
//返回该键对应的通道
client = (SocketChannel)selectionKey.channel();
String sendMessage = "Send form Server...Hello... "+new Random().nextInt(100)+" .";
//向缓冲区中写入数据
sendBuffer.put(sendMessage.getBytes());
//put了数据,标志位被改变
sendBuffer.flip();
//数据输出到通道
client.write(sendBuffer);
System.out.println("Server:服务器向客户端发送数据:" + sendMessage);
client.register(selector, SelectionKey.OP_READ);
}


}


public static void main(String[] args) {

try {

NioServer nioServer = new NioServer();
nioServer.linstenr();

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}


}


二、Nio Client 实例

package com.zhuoxuan.net.nio;

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;
import java.util.Set;

/**
*
* <p>
* nio client
* </p>
*
* @author 卓轩
* @创建时间:2014年7月7日
* @version: V1.0
*/
public class NioClient {

private static final int BLOCK_SIZE = 4096;

private static ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK_SIZE);

private static ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK_SIZE);

private static final InetSocketAddress SERVER_ADDRESS = new InetSocketAddress("127.0.0.1",8787);


public static void main(String[] args) {

try {
//打开socket通道
SocketChannel socketChannel = SocketChannel.open();
//设置为非阻塞模式
socketChannel.configureBlocking(false);
//打开选择器
Selector selector = Selector.open();
//向selector 选择器注册此通道
socketChannel.register(selector, SelectionKey.OP_CONNECT);
//链接
socketChannel.connect(SERVER_ADDRESS);

SocketChannel client;
while (true) {
//选择一组键
selector.select();
//返回此选择器的已选择键集
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
//遍历对应的 SelectionKey 处理
while (iterator.hasNext()) {
SelectionKey selectionKey = (SelectionKey) iterator.next();
//判断此键的通道是否已完成其套接字连接操作
if (selectionKey.isConnectable()) {
System.out.println("Client: already connected.");
client = (SocketChannel)selectionKey.channel();
//判断该通道是否进行连接过程、完成连接过程
if(client.isConnectionPending()){
client.finishConnect();

sendBuffer.clear();
sendBuffer.put("hello nio server".getBytes());
sendBuffer.flip();

client.write(sendBuffer); //将数据写入该通道
client.register(selector, SelectionKey.OP_READ);
}
}
else if(selectionKey.isReadable()){
//获取该键中对应的通道
client = (SocketChannel)selectionKey.channel();

receiveBuffer.clear();
int count = client.read(receiveBuffer);
if(count > 0){
String receiveMessage = new String(receiveBuffer.array(),0,count);
System.out.println("Client:接收到来自Server的消息," + receiveMessage);
client.register(selector, SelectionKey.OP_WRITE);
}
}
else if(selectionKey.isWritable()){
sendBuffer.clear();
client = (SocketChannel) selectionKey.channel();
String sendText = "hello server,key..";
sendBuffer.put(sendText.getBytes());
//将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
sendBuffer.flip();
client.write(sendBuffer);
System.out.println("Client:客户端向服务器端发送数据--:"+sendText);
client.register(selector, SelectionKey.OP_READ);

}
}
selectionKeys.clear();
Thread.sleep(3000);
}





} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}



}