码迷,mamicode.com
首页 > 编程语言 > 详细

Java NIO初试

时间:2015-04-29 16:30:29      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:

Java的NIO采用selector来轮循,还是不错,小试牛刀,下附代码

Server:

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 NIOServer {
	private Selector selector;

	public void initServer(int port) throws IOException {
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();// 打开服务器套接字通道
		serverSocketChannel.configureBlocking(false);// 设置为非阻塞模式
		serverSocketChannel.socket().bind(new InetSocketAddress(port));// 绑定端口
		this.selector = Selector.open();// 打开选择器
		// 注册事件,当事件到达,selector。select()会返回,如果没有事件会一直阻塞
		serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);// 注册选择器,接受客户端连接
	}

	public void listen() throws IOException {
		System.out.println("服务器启动!开始轮询监听消息");
		while (true) {
			int ready = this.selector.select();
			if (ready == 0) {
				continue;
			}
			Iterator items = this.selector.selectedKeys().iterator();
			while (items.hasNext()) {
				SelectionKey key = (SelectionKey) items.next();
				// 删除已经选择的key,防止重复处理
				items.remove();
				// 请求连接
				if (key.isAcceptable()) {
					ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key
							.channel();
					if (serverSocketChannel == null) {
						continue;
					}
					SocketChannel socketChannel = serverSocketChannel.accept();//每次接受新的连接请求会产生新的通道,
					socketChannel.configureBlocking(false);
					socketChannel.write(ByteBuffer.wrap(new String(
							"你好,客户端,连接已建立,可以开始通信!").getBytes()));//连接成功,发消息给客户端
					System.out.println("连接已经建立");
					socketChannel.register(this.selector, SelectionKey.OP_READ);//准备好接收数据
				} else if (key.isReadable()) {
					this.read(key);
				}
			}
		}
	}

	public void read(SelectionKey key) throws IOException {
		SocketChannel socketChannel = (SocketChannel) key.channel();
		ByteBuffer byteBuffer = ByteBuffer.allocate(100);
		socketChannel.read(byteBuffer);
		byte[] data = byteBuffer.array();
		String msg = new String(data).trim();
		if (msg.equals("close~!@#$%")) {//收到关闭指令,发送确认关闭的指令给客户端,结束自身通道
			ByteBuffer sendBuffer = ByteBuffer.wrap(new String("bye close").getBytes());
			while (sendBuffer.hasRemaining()) {
				socketChannel.write(sendBuffer);
			}
			socketChannel.close();
			System.out.println("已经关闭");
		} else {
			System.out.println("server Receive:" + msg);//服务器收到任何消息都会给客户端发送"收到"
			socketChannel.write(ByteBuffer.wrap(new String("收到!").getBytes()));
		}
	}

	public static void main(String[] args) {
		NIOServer server = new NIOServer();
		try {
			server.initServer(1377);
			server.listen();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

  Client:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
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 NIOClient {
	private Selector selector;
	//初始化
	public void initClient(String ipAddress, int port) throws IOException {
		SocketChannel socketChannel = SocketChannel.open();//打开套接字通道
		socketChannel.configureBlocking(false);//非阻塞
		this.selector = Selector.open();//打开选择器
		socketChannel.connect(new InetSocketAddress(ipAddress, port));//指定ip地址和端口号用于连接
		socketChannel.register(this.selector, SelectionKey.OP_CONNECT);//通道注册到选择器中,用于连接
	}
	//监听
	public void listen() throws IOException {
		while (true) {
			//当客户端关闭的时候需要结束轮循的动作,这样程序才会结束
			if (!this.selector.isOpen()) {
				return;
			}
			int ready = this.selector.select();//这个才是真正的轮循啦,得到通道
			if (ready == 0) {
				continue;//如果selector中没有SocketChannel,直接开始下一次咯 
			}
			Iterator items = this.selector.selectedKeys().iterator();
			while (items.hasNext()) {
				SelectionKey key = (SelectionKey) items.next();
				items.remove();//防止重复处理
				if (key.isConnectable()) {//连接
					System.out.println("正在连接,连接成功后,服务器会返回结果!");
					SocketChannel socketChannel = (SocketChannel) key.channel();
					// 如果正在连接,则完成连接
					if (socketChannel.isConnectionPending()) {
						socketChannel.finishConnect();
					}
					socketChannel.register(this.selector, SelectionKey.OP_READ);//重新注册该通道,用于读取数据
				} else if (key.isReadable()) {//读取
					this.read(key);
				}
			}
		}
	}

	/****************************************************/
	/*
	 * 客户端关闭思路
	 * 客户端							服务器
	 * 
	 * 用户输入bye,需要关闭客户端
	 * 
	 * "close~!@#$%"	->			"close~!@#$%"                               约定好的内容("close~!@#$%")
	 * 					
	 * "bye close"	<-				"bye close"     ----->服务器通道关闭        				约定好的内容("bye close")
	 * 
	 * 客户端通道关闭					服务器还可以接受别的请求
	 * 
	 */
	public void read(SelectionKey key) throws IOException {
		SocketChannel socketChannel = (SocketChannel) key.channel();
		ByteBuffer receiveBuffer = ByteBuffer.allocate(100);
		socketChannel.read(receiveBuffer);
		byte[] data = receiveBuffer.array();
		String msg = new String(data).trim();
		if (msg.equals("bye close")) {//客户端和服务器约定关闭,收到服务器响应后可以关闭
			System.out.println("关闭");
			socketChannel.close();
			this.selector.close();
			return;
		}
		System.out.println("client receive:" + msg);
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		String readMsg = reader.readLine();
		ByteBuffer sendBuffer = ByteBuffer.allocate(256);
		sendBuffer.clear();
		if(readMsg.equals("bye")){//告诉服务器,准备要撤退,当服务器返回bye close,关闭通道和选择器
			System.out.println("准备关闭");
			sendBuffer.put("close~!@#$%".getBytes());
			sendBuffer.flip();
		}else{
			sendBuffer.put(readMsg.getBytes());
			sendBuffer.flip();
		}
		while (sendBuffer.hasRemaining()) {
			socketChannel.write(sendBuffer);
		}
	}

	public static void main(String[] args) {
		NIOClient client = new NIOClient();
		try {
			client.initClient("127.0.0.1", 1377);
			client.listen();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

  客户端可开启多个,用于连接服务器端,亲测可用,有问题联系作者,xusong1313@qq.com

业务逻辑可自己完善,其实建议的搭建不难

Java NIO初试

标签:

原文地址:http://www.cnblogs.com/weiki/p/4465958.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!