1.java nio 网络编程 Server端

    最近一段时间看了下java nio,对于它的实际用途还有待继续研究,也看了网上很多人的文章博客等,收益颇多,但是还是自己动手才能知道自己是否真的会写了,会写与是否理解nio工作机制还有一定距离。我又不是一个理论派,主要还是讲究实战的,好,废话不多说,直接准备动作写。

    首先你需要了解几个nio网络编程中会用到的组件(类):

    1.ByteBuffer

    2.Selector

    3.ServerSocketChannel

    4.SocketChannel

    5.SelectionKey

    

    说一下nio server的整体实现思路:

    打开Selector--》 打开ServerSocketChannel --> 配置ServerSocketChannel是否阻塞 --》 绑定ServerSocketChannel到某个主机以及端口 --》给ServerSocketChannel注册一个Selector --》 ServerSocketChannel监听accept事件 --》 客户端连接后获取SocketChannel --》 响应SocketChannel上的read/write事件

 

    我写的可能和网络上一些人写的稍微有点不太一样,这也没办法,网络上打开10篇nio相关文章,有好几篇都是一样的,你抄我,我抄你的。个个图文并茂,个个都是架构师,分析reactor设计模式,多路复用,高性能,讲的头头是道,不过这和我没什么关系,我体会不到,应该是我太菜了。所以还是来点简单的,基础打好,总归不会有害处。

 

    下面是具体实现代码:把这个代码拷贝到你的ide中,然后运行,用tcp连接工具,比如putty,cmd也行,不过cmd没有那么好用。有两个例子,第一个是只能少量字符传输,第二个支持大文本传输。

 

    demo1:

package com.govert.project;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
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;
import java.util.Random;
import java.util.Set;

/**
 * 少量字符传输
 */
public class NioServer {

    public static void main(String[] args) throws IOException {
        // read and write byte buffer
        ByteBuffer rb = ByteBuffer.allocate(1024);
        ByteBuffer wb = ByteBuffer.allocate(1024);

        // listen hostname and port
        String hostname = "127.0.0.1";
        int port = 9000;

        // open Selector & check
        Selector selector = Selector.open();
        if (selector.isOpen()) {
            System.err.println("selector open success.");
        }

        // open ServerSocketChannel & check
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        if (serverSocketChannel.isOpen()) {
            System.err.println("serverSocketChannel open success.");
        }

        // ServerSocketChannel config non-block & bind hostname and port
        serverSocketChannel.configureBlocking(false);
        // serverSocketChannel.socket().bind(new InetSocketAddress(hostname, port));// old way bind
        serverSocketChannel.bind(new InetSocketAddress(hostname, port));// 1.7+

        // ServerSocketChannel register selector
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // handle event loop
        while (true) {

            selector.select();

            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> kit = keys.iterator();
            while (kit.hasNext()) {
                SelectionKey key = kit.next();

                // read event
                if (key.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) key.channel();

                    rb.clear();
                    socketChannel.read(rb);
                    rb.flip();
                    System.err.println("client request data: " + new String(rb.array(), 0, rb.limit(), "utf-8"));
                    //
                    key.interestOps(SelectionKey.OP_WRITE);
                }
                // write event
                else if (key.isWritable()) {
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    String resp = "server response data: " + new Random().nextInt(1000) + 1 + "\r\n";
                    wb.clear();
                    wb.put(resp.getBytes("utf-8"));
                    wb.flip();
                    socketChannel.write(wb);

                    //
                    key.interestOps(SelectionKey.OP_READ);
                }
                // accept event
                else if (key.isAcceptable()) {
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }
            }

            // clear keys
            keys.clear();
        }
    }

}
 

  

    demo2:

package com.govert.project;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;

/**
 * 大文本传输
 */
public class NioServer {

    public static void main(String[] args) throws IOException {
        // read and write byte buffer
        ByteBuffer rb = ByteBuffer.allocate(1024);
        ByteBuffer wb = ByteBuffer.allocate(1024);

        // listen hostname and port
        String hostname = "127.0.0.1";
        int port = 9000;

        // open Selector & check
        Selector selector = Selector.open();
        if (selector.isOpen()) {
            System.err.println("Selector open success.");
        }

        // open ServerSocketChannel & check
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        if (serverSocketChannel.isOpen()) {
            System.err.println("ServerSocketChannel open success.");
        }

        // ServerSocketChannel config non-block & bind hostname and port
        serverSocketChannel.configureBlocking(false);
        // serverSocketChannel.socket().bind(new InetSocketAddress(hostname, port));// old way bind
        serverSocketChannel.bind(new InetSocketAddress(hostname, port));// 1.7+

        // ServerSocketChannel register selector
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // handle event loop
        while (true) {

            selector.select();

            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> kit = keys.iterator();
            while (kit.hasNext()) {
                SelectionKey key = kit.next();

                // read event
                if (key.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) key.channel();

                    // large text
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    StringBuilder sb = new StringBuilder();
                    while (true) {
                        if (socketChannel.read(rb) < 1 && rb.hasRemaining()) break;
                        rb.flip();
                        baos.write(rb.array(), 0, rb.limit());
                        rb.clear();
                    }
                    //
                    System.err.println("client request data: " + new String(baos.toByteArray(), 0, baos.size(), "utf-8"));
                    //
                    key.interestOps(SelectionKey.OP_WRITE);
                }
                // write event
                else if (key.isWritable()) {
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    // large response
                    StringBuilder sb = new StringBuilder();
                    for (int i = 1; i < 1001; i++) {
                        sb.append("server respnse data: 第" + i + "条响应结果.\r\n");
                    }
                    byte[] bytes = sb.toString().getBytes("utf-8");
                    int length = bytes.length;
                    int loop = (length + 1023) / 1024;
                    int lastLoop = loop - 1;
                    int len;
                    for (int i = 0; i < loop; i++) {
                        if (i == lastLoop) len = length - i * 1024;
                        else len = 1024;
                        wb.put(bytes, i * 1024, len);
                        wb.flip();
                        socketChannel.write(wb);
                        wb.clear();
                    }

                    //
                    key.interestOps(SelectionKey.OP_READ);
                }
                // accept event
                else if (key.isAcceptable()) {
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }
            }

            // clear keys
            keys.clear();
        }
    }

}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值