Java NIO(6):Server和Client案例

Server:

package com.tony.app;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
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.Set;

/**
 * 服务器
 * 
 * @author TONY
 *
 */
public class Server {
	// 缓冲区的大小
	private final static int BUFFER_SIZE = 1024;

	// 缓冲区
	private ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);

	// Server监听的端口号
    // private final static int PORT = 8888;

	// 选择器
	private Selector selector = null;

	// 初始化工作
	public void init(int port) throws IOException {
		System.out.println("============ Listening On Port : " + port + "============");
		// 打开服务器套接字通道
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		// 设置为非阻塞状态
		serverSocketChannel.configureBlocking(false);
		// 获取通道相关联的套接字
		ServerSocket serverSocket = serverSocketChannel.socket();
		// 绑定端口号
		serverSocket.bind(new InetSocketAddress(port));
		// 打开一个选择器
		selector = Selector.open();
		// 服务器套接字注册到Selector中 并指定Selector监控连接事件
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
	}

	public void listen() throws IOException {
		while (true) {
			// 开启选择
			int readyChannels = selector.select(); // 没有通道就绪 一直阻塞 返回已经就绪通道的数目(有可能为0)
			if (readyChannels == 0) {
				continue;
			}
			// 返回已选择键的集合
			Set selectedKeys = selector.selectedKeys();
			// 遍历键 并检查键对应的通道里注册的就绪事件
			Iterator iterator = selectedKeys.iterator();
			while (iterator.hasNext()) {
				// SelectionKey封装了一个通道和选择器的注册关系
				SelectionKey key = (SelectionKey) iterator.next();
				handleKey(key);
				// Selector不会移除SelectionKey 处理完了手动移除
				iterator.remove();
			}
		}
	}

	// 处理SelectionKey
	private void handleKey(SelectionKey key) throws IOException {
		// 是否有连接进来
		if (key.isAcceptable()) {
			ServerSocketChannel server = (ServerSocketChannel) key.channel();// 获取通道 转化为要处理的类型
			SocketChannel socketChannel = server.accept();
			// SocketChannel通道的可读事件注册到Selector中
			registerChannel(selector, socketChannel, SelectionKey.OP_READ);
			// 连接成功 向Client打个招呼
			if (socketChannel.isConnected()) {
				buffer.clear();
				buffer.put("I am Server...".getBytes());
				buffer.flip();
				socketChannel.write(buffer);

			}

		}
		// 通道的可读事件就绪
		if (key.isReadable()) {
			SocketChannel socketChannel = (SocketChannel) key.channel();
			buffer.clear(); // 清空缓冲区
			// 读取数据
			int len = 0;
			while ((len = socketChannel.read(buffer)) > 0) {
				buffer.flip();
				while (buffer.hasRemaining()) {
					System.out.println("Server读取的数据:" + new String(buffer.array(), 0, len));
				}
			}
			if (len < 0) {
				// 非法的SelectionKey 关闭Channel
				socketChannel.close();
			}
			// SocketChannel通道的可写事件注册到Selector中
			registerChannel(selector, socketChannel, SelectionKey.OP_WRITE);
		}
		// 通道的可写事件就绪
		if (key.isWritable()) {
			SocketChannel socketChannel = (SocketChannel) key.channel();
			buffer.clear(); // 清空缓冲区
			// 准备发送的数据
			String message_from_server = "Hello,Client... " + socketChannel.getLocalAddress();
			buffer.put(message_from_server.getBytes());
			buffer.flip();
			socketChannel.write(buffer);
			System.out.println("Server发送的数据:" + message_from_server);
			// SocketChannel通道的可写事件注册到Selector中
			registerChannel(selector, socketChannel, SelectionKey.OP_READ);
		}

	}

	// 注册通道到指定Selector上
	private void registerChannel(Selector selector, SelectableChannel channel, int ops) throws IOException {
		if (channel == null) {
			return;
		}
		channel.configureBlocking(false);
		// 注册通道
		channel.register(selector, ops);

	}
	
	public static void main(String[] args) throws IOException {
		Server server = new Server();
		server.init(8888);
		server.listen();
	}
}

Client:

package com.tony.app;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * 客户端
 * 
 * @author TONY
 *
 */
public class Client {

	// 缓冲区的大小
	private final static int BUFFER_SIZE = 1024;
	// 缓冲区
	private ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);

	// 选择器
	private Selector selector = null;

	private final static int PORT = 8888;

	// 初始化工作
	public void init(String address) throws IOException {

		// 打开客户端套接字通道
		SocketChannel socketChannel = SocketChannel.open();
		// 设置为非阻塞状态
		socketChannel.configureBlocking(false);
		// 打开选择器
		selector = Selector.open();
		// 注册
		socketChannel.register(selector, SelectionKey.OP_CONNECT);
		// 发起连接
		socketChannel.connect(new InetSocketAddress(address, PORT));

	}

	public void connect() throws IOException {
		while (true) {
			int readyChannels = selector.select();
			if (readyChannels == 0) {
				continue;
			}
			// 返回已选择键的集合
			Set selectedKeys = selector.selectedKeys();
			// 遍历键 并检查键对应的通道里注册的就绪事件
			Iterator iterator = selectedKeys.iterator();
			while (iterator.hasNext()) {
				// SelectionKey封装了一个通道和选择器的注册关系
				SelectionKey key = (SelectionKey) iterator.next();
				handleKey(key);
				// Selector不会移除SelectionKey 处理完了手动移除
				iterator.remove();
			}
		}
	}

	// 处理SelectionKey
	private void handleKey(SelectionKey key) throws IOException {
		// 是否可连接
		if (key.isConnectable()) {
			SocketChannel socketChannel = (SocketChannel) key.channel();
			// 完成连接
			if(socketChannel.isConnectionPending()) {
				socketChannel.finishConnect();
				System.out.println("连接成功...");
				// 发送数据给Server
				String message_to_server = "Hello,Server...";
				buffer.clear();
				buffer.put(message_to_server.getBytes());
				buffer.flip();
				socketChannel.write(buffer);
				System.out.println("Client发送的数据:" + message_to_server);
				registerChannel(selector, socketChannel, SelectionKey.OP_READ);
			}else {
				System.exit(1); // 连接失败 退出
			}
			

		}
		// 通道的可读事件就绪
		if (key.isReadable()) {
			SocketChannel socketChannel = (SocketChannel) key.channel();
			buffer.clear(); // 清空缓冲区
			// 读取数据
			int len = 0;
			while ((len = socketChannel.read(buffer)) > 0) {
				buffer.flip();
				while (buffer.hasRemaining()) {
					System.out.println("Client读取的数据:" + new String(buffer.array(), 0, len));
				}
			}
			if (len < 0) {
				// 非法的SelectionKey 关闭Channel
				socketChannel.close();
			}
			// SocketChannel通道的可写事件注册到Selector中
			registerChannel(selector, socketChannel, SelectionKey.OP_WRITE);
		}
		// 通道的可写事件就绪
		if (key.isWritable()) {
			SocketChannel socketChannel = (SocketChannel) key.channel();
			buffer.clear(); // 清空缓冲区
			// 准备发送的数据
			String message_from_server = "Hello,Server... " + socketChannel.getLocalAddress();
			buffer.put(message_from_server.getBytes());
			buffer.flip();
			socketChannel.write(buffer);
			System.out.println("Client发送的数据:" + message_from_server);
			// SocketChannel通道的可写事件注册到Selector中
			registerChannel(selector, socketChannel, SelectionKey.OP_READ);
		}

	}

	// 注册通道到指定Selector上
	private void registerChannel(Selector selector, SelectableChannel channel, int ops) throws IOException {
		if (channel == null) {
			return;
		}
		channel.configureBlocking(false);
		// 注册通道
		channel.register(selector, ops);

	}
	
	public static void main(String[] args) throws IOException {
		Client client = new Client();
		client.init("localhost");
		client.connect();
	}

}

你可能感兴趣的:(Java NIO(6):Server和Client案例)