Java网络编程-Nio 实例代码

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();
		}

	}

}

Java网络编程-Nio 实例代码

时间: 2024-08-05 09:25:32

Java网络编程-Nio 实例代码的相关文章

JAVA网络编程-NIO之Channel

Java NIO的通道类似流,但又有些不同: 既可以从通道中读取数据,又可以写数据到通道.但流的读写通常是单向的. 通道可以异步地读写. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入. Channel的实现 这些是Java NIO中最重要的通道的实现: FileChannel:从文件中读写数据(不可异步读写) DatagramChannel: 能通过UDP读写网络中的数据 SocketChannel:能通过TCP读写网络中的数据 ServerSocketChann

Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO

Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO https://blog.csdn.net/column/details/21963.html 部分代码会放在我的的Github:https://github.com/h2p

Java网络编程和NIO详解开篇:Java网络编程基础

Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为我们拥有网络.网络是一个神奇的东西,它改变了你和我的生活方式,改变了整个世界. 然而,网络的无标度和小世界特性使得它又是复杂的,无所不在,无所不能,以致于我们无法区分甚至无法描述. 对于一个码农而言,了解网络的基础知识可能还是从了解定义开始,认识OSI的七层协议模型,深入Socket内部,进而熟练地

Java网络编程和NIO详解6:Linux epoll实现原理详解

Java网络编程和NIO详解6:Linux epoll实现原理详解 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO https://blog.csdn.net/column/details/21963.html 部分代码会放在我的的Github:https://github.com/h2pl/ Linux epoll实现原理详解 在linux 没有实现epoll事件驱动机制之前,我们一般选择用select或者pol

Java网络编程和NIO详解9:基于NIO的网络编程框架Netty

Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introduction/ netty是基于NIO实现的异步事件驱动的网络编程框架,学完NIO以后,应该看看netty的实现,netty框架涉及的内容特别多,这里只介绍netty的基本使用和实现原理,更多扩展的内容将在以后推出. 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎

Java网络编程和NIO详解4:浅析NIO包中的Buffer、Channel 和 Selector

Java网络编程与NIO详解4:浅析NIO包中的Buffer.Channel 和 Selector 转自https://www.javadoop.com/post/nio-and-aio 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO https://blog.csdn.net/column/details/21963.html 部分代码会放在我的的Github:https://github.com/h2pl/ J

Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO https://blog.csdn.net/column/details/21963.html 部分代码会放在我的的Github:https://github.com/h2pl/ 浅谈 Linux

Java网络编程基础(六)— 基于TCP的NIO简单聊天系统

在Java网络编程基础(四)中提到了基于Socket的TCP/IP简单聊天系统实现了一个多客户端之间护法消息的简单聊天系统.其服务端采用了多线程来处理多个客户端的消息发送,并转发给目的用户.但是由于它是基于Socket的,因此是阻塞的. 本节我们将通过SocketChannel和ServerSocketChannel来实现同样的功能. 1.客户端输入消息的格式 username:msg    username表示要发送的的用户名,msg为发送内容,以冒号分割 2.实现思路 实现思路与Java网络

Java网络编程和NIO详解8:浅析mmap和Direct Buffer

Java网络编程与NIO详解8:浅析mmap和Direct Buffer 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO https://blog.csdn.net/column/details/21963.html 部分代码会放在我的的Github:https://github.com/h2pl/ Java网络编程与NIO详解8:浅析mmap和Direct Buffer 之前看到一篇文章说epoll中在维护epo