贴下课堂笔记:
在 Java 中使用 NIO 进行网络 TCP 套接字编程主要以下几个类:
ServerSocketChannel: 服务端套接字通道, 主要监听接收客户端请求
Selector: 通道选择器, 主要用于管理服务端通道和所有客户端通道 (监听通道中发生的事件), 也就说是一个多路通道复用器.
SelectorKey: 事件选择键
SocketChannel: 套接字通道 (客户端)
这篇文章《NIO 编程中的 SelectionKey.interestOps 方法中的逻辑运算》解决了我一些疑问, 地址: https://blog.csdn.net/woaiqianzhige/article/details/78696188
NIO 套接字服务端开发步骤:
创建选择器
启动服务端通道
设置服务端通道为非阻塞模式
将服务端通道注册到选择器
轮训通道事件
处理通道事件
关闭通道 (可选)
案例: 服务端接收客户端发送的短信息, 服务端回复已收到.
服务端代码:
- import java.io.IOException;
- import java.NET.InetSocketAddress;
- import java.nio.ByteBuffer;
- import java.nio.channels.ClosedChannelException;
- 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;
- public class Server {
- private Selector selector;
- private ServerSocketChannel serverSocketChannel;
- private ByteBuffer byteBuffer = ByteBuffer.allocate(8192);
- /**
- * 构造方法 启动服务器
- *
- * @param port
- * @throws IOException
- */
- public Server() {
- try {
- selector = Selector.open();
- serverSocketChannel = ServerSocketChannel.open();
- serverSocketChannel.configureBlocking(false);
- serverSocketChannel.bind(new InetSocketAddress(10086));
- serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
- System.out.println("Server start successful with port: 10086");
- } catch (ClosedChannelException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) throws Exception {
- new Server().start();
- }
- private void start() {
- while (true) {
- try {
- selector.select();
- Set<SelectionKey> keys = selector.selectedKeys();
- Iterator<SelectionKey> keyIterator = keys.iterator();
- while (keyIterator.hasNext()) {
- SelectionKey key = keyIterator.next();
- keyIterator.remove();
- if (!key.isValid()) {
- continue;
- }
- if (key.isAcceptable()) {
- accept(key);
- }
- if (key.isReadable()) {
- receive(key);
- }
- if (key.isWritable()) {
- reply(key);
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- private void reply(SelectionKey key) {
- try {
- SocketChannel socketChannel = (SocketChannel) key.channel();
- byteBuffer.clear();
- String message = "receive success";
- byteBuffer.put(message.getBytes());
- byteBuffer.flip();
- socketChannel.write(byteBuffer);
- System.out.println("reply:" + message);
- byteBuffer.clear();
- key.interestOps(SelectionKey.OP_READ);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- private void receive(SelectionKey key) {
- try {
- SocketChannel socketChannel = (SocketChannel) key.channel();
- byteBuffer.clear();
- int flag = socketChannel.read(byteBuffer);
- if (flag == -1) {
- key.channel().close();
- key.cancel();
- return;
- }
- byteBuffer.flip();
- byte[] buf = new byte[byteBuffer.remaining()];
- byteBuffer.get(buf);
- String message = new String(buf);
- System.out.println("receive message:" + message);
- byteBuffer.clear();
- key.interestOps(SelectionKey.OP_WRITE);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- private void accept(SelectionKey key) {
- try {
- SocketChannel socketChannel = serverSocketChannel.accept();
- socketChannel.configureBlocking(false);
- socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
- System.out.println(Thread.currentThread().getName() + ": create client channel.");
- } catch (ClosedChannelException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
客户端代码:
- import java.io.IOException;
- import java.NET.InetSocketAddress;
- import java.nio.ByteBuffer;
- import java.nio.channels.ClosedChannelException;
- import java.nio.channels.SelectionKey;
- import java.nio.channels.Selector;
- import java.nio.channels.SocketChannel;
- import java.util.Iterator;
- import java.util.Scanner;
- public class Client {
- private Selector selector;
- private ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
- private SocketChannel socketChannel;
- public Client() {
- try {
- selector = Selector.open();
- socketChannel = SocketChannel.open();
- socketChannel.configureBlocking(false);
- socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
- socketChannel.connect(new InetSocketAddress("127.0.0.1", 10086));
- System.out.println("Client start successful");
- } catch (ClosedChannelException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- new Client().start();
- }
- private void start() {
- while (true) {
- try {
- selector.select();
- Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
- while (keys.hasNext()) {
- SelectionKey key = keys.next();
- keys.remove();
- if (!key.isValid()) {
- continue;
- }
- if (key.isConnectable()) {
- if (socketChannel.finishConnect()) {
- key.interestOps(key.interestOps() & ~SelectionKey.OP_CONNECT);
- System.out.println("Client connect server success");
- }
- }
- if (key.isReadable()) {
- receive(key);
- }
- if (key.isWritable()) {
- reply(key);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- private void reply(SelectionKey key) {
- try {
- @SuppressWarnings("resource")
- Scanner scanner = new Scanner(System.in);
- byteBuffer.clear();
- System.out.println("please input message:");
- String message = scanner.next();
- byteBuffer.put(message.getBytes());
- byteBuffer.flip();
- socketChannel.write(byteBuffer);
- byteBuffer.clear();
- System.out.println("send message:" + message);
- key.interestOps(SelectionKey.OP_READ);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- private void receive(SelectionKey key) {
- try {
- byteBuffer.clear();
- socketChannel.read(byteBuffer);
- byteBuffer.flip();
- byte[] bytes = new byte[byteBuffer.remaining()];
- byteBuffer.get(bytes);
- String message = new String(bytes).trim();
- System.out.println("receive message:" + message);
- byteBuffer.clear();
- key.interestOps(SelectionKey.OP_WRITE);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
真是粗心大意了... 特发此博文给我自己涨涨记性
来源: http://www.bubuko.com/infodetail-2963668.html