NIO

package nio;

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

public class Server implements Runnable {
	private Selector selector;
	private ByteBuffer readBuffer = ByteBuffer.allocate(1024);
	private ByteBuffer writeBuffer = ByteBuffer.allocate(2014);

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

	public Server(int port) {
		init(port);
	}

	private void init(int port) {
		try {
			System.out.println("server starting at port" + port + "....");
			// 开启多路复用器
			this.selector = Selector.open();
			ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
			serverSocketChannel.configureBlocking(false);
			serverSocketChannel.bind(new InetSocketAddress(port));
			/*
			 * register(Selector,int) int - 状态编码 OP_ACCEPT : 连接成功的标记位 OP_READ : 可以读取数据的标记
			 * OP_WRITE : 可以写入数据的标记
			 * 
			 */
			serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
			System.out.println("server started");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
			try {
				// 阻塞方法,当至少有一个通道被选中,此方法返回,通道是否返回由多路复用器的通道标记决定
				this.selector.select();
				Iterator<SelectionKey> keys = this.selector.selectedKeys().iterator();
				while (keys.hasNext()) {
					SelectionKey key = keys.next();
					keys.remove();
					if (key.isValid()) {
						try {
							if (key.isAcceptable()) {
								accept(key);
							}
						} catch (Exception e) {
							key.cancel(); // disconnect
						}
						try {
							if (key.isReadable()) {
								read(key);
							}
						} catch (Exception e) {
							key.cancel(); // disconnect
						}
						try {
							if (key.isWritable()) {
								write(key);
							}
						} catch (Exception e) {
							key.cancel(); // disconnect
						}

					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	private void write(SelectionKey key) {
		this.writeBuffer.clear();
		SocketChannel socketChannel = (SocketChannel)key.channel();
		Scanner scanner = new Scanner(System.in);
		try {
			System.out.println("put message for send to client");
			String line = scanner.nextLine();
			writeBuffer.put(line.getBytes("UTF-8"));
			writeBuffer.flip();
			socketChannel.write(writeBuffer);
			socketChannel.register(this.selector, SelectionKey.OP_READ);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void read(SelectionKey key) {
		try {
			this.readBuffer.clear();
			SocketChannel socketChannel = (SocketChannel)key.channel();
			//将通道中的数据读取到缓存中 通道中的数据就是客户端发送给服务器的数据
			int readLength = socketChannel.read(readBuffer);
			//检查客户端是否写入数据
			if(readLength==-1) {
				key.channel().close();
				key.cancel();
				return;
			}
			/*flip是游标重置  NIO中最复杂的操作 就是buffer的控制
			* Buffer中有一个游标 游标信息在操作后不会归零 
			*/
			this.readBuffer.flip();
			byte[] data = new byte[readBuffer.remaining()];
			readBuffer.get(data);
			System.out.println("from " + socketChannel.getRemoteAddress()+ " client: " + new String(data,"UTF-8")); 
			socketChannel.register(this.selector, SelectionKey.OP_WRITE);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void accept( SelectionKey key) {
		try {
			//此通道是init方法中注册到selector上的serverSocketChannel
			ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel();
			//阻塞方法 当客户端发起请求后返回 此通道与客户端一一对应
			SocketChannel socketChannel = serverSocketChannel.accept();
			socketChannel.configureBlocking(false);
			//设置对应客户端的通道标记状态 此通道读取数据用
			socketChannel.register(this.selector, SelectionKey.OP_READ);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
package nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;

public class Clinet {
	public static void main(String[] agrs0) {
		InetSocketAddress remoAddress = new InetSocketAddress("localhost",9999);
		SocketChannel socketChannel = null;
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		try {
			socketChannel = SocketChannel.open();
			socketChannel.connect(remoAddress);
			Scanner scanner = new Scanner(System.in);
			while (true) {
				System.out.println("put message for send to server");
				String line = scanner.nextLine();
				if(line.equals("exit")) {
					break;
				}
				buffer.put(line.getBytes("UTF-8"));
				buffer.flip();
				socketChannel.write(buffer);
				buffer.clear();
				//读取服务器返回的数据
				int readLength = socketChannel.read(buffer);
				if(readLength == -1) {
					break;
				}
				buffer.flip();
				byte[] data = new byte[buffer.remaining()];
				buffer.get(data);
				System.out.print("from server: "+new String(data,"UTF-8"));
				buffer.clear();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值