`
szuyork
  • 浏览: 2668 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论

浅谈JavaNIO使用

阅读更多

  代碼分爲客戶端、服務端以及調試代碼

客戶端:

package test.nio.tcp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

class AsyncClient
{
    private SocketChannel sc;
    private final int MAX_LENGTH = 1024;
    private ByteBuffer r_buff = ByteBuffer.allocate(MAX_LENGTH);
    private ByteBuffer w_buff = ByteBuffer.allocate(MAX_LENGTH);
    private static String host;
    private static int port = 6000;

    public AsyncClient()
    {
        try
        {
            InetSocketAddress addr = new InetSocketAddress(host, port);
            // 生成一个socketchannel
            sc = SocketChannel.open();

            // 连接到server
            sc.connect(addr);
            while (!sc.finishConnect());
            System.out.println("connection has been established!...");

            while (true)
            {
//                // 回射消息
//                String echo = null;
//                try
//                {
//                    System.err.println("Enter msg you'd like to send:  ");
//                    BufferedReader br = new BufferedReader(
//                        new InputStreamReader(System.in));
//                    // 输入回射消息
//                    echo = br.readLine();
//                    echo = "send [test] to server.";
//
//                    // 把回射消息放入w_buff中
//                    w_buff.clear();
//                    w_buff.put(echo.getBytes());
//                    w_buff.flip();
//                }
//                catch (IOException ioe)
//                {
//                    System.err.println("sth. is wrong with br.readline() ");
//                }
//
//                // 发送消息
//                while (w_buff.hasRemaining())
//                    sc.write(w_buff);
//                w_buff.clear();

                // 进入接收状态
                Rec();
                // 间隔1秒
                //Thread.currentThread().sleep(1000);
            }
        }
        catch (IOException ioe)
        {
            ioe.printStackTrace();
        }
//        catch (InterruptedException ie)
//        {
//            ie.printStackTrace();
//        }
    }

    // //////////
    // 读取server端发回的数据,并显示
    public void Rec() throws IOException
    {
        int count;
        r_buff.clear();
        count = sc.read(r_buff);
        r_buff.flip();
        byte[] temp = new byte[r_buff.limit()];
        r_buff.get(temp);
        System.out.println("reply is [" + count + "] long, and content is: "
            + new String(temp));
    }

    public static void main(String args[])
    {
//        if (args.length < 1)
//        {// 输入需有主机名或IP地址
//            try
//            {
//                System.err.println("Enter host name: ");
//                BufferedReader br = new BufferedReader(new InputStreamReader(
//                    System.in));
//                host = br.readLine();
//            }
//            catch (IOException ioe)
//            {
//                System.err.println("sth. is wrong with br.readline() ");
//            }
//        }
//        else if (args.length == 1)
//        {
//            host = args[0];
//        }
//        else if (args.length > 1)
//        {
//            host = args[0];
//            port = Integer.parseInt(args[1]);
//        }
        host = "127.0.0.1";
        port = 6000;
        new AsyncClient();
    }
}

服務端:

package test.nio.tcp;

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;

class AsyncServer implements Runnable
{
    private ByteBuffer r_buff = ByteBuffer.allocate(1024);
    private ByteBuffer w_buff = ByteBuffer.allocate(1024);
    private static int port = 7890;

    public AsyncServer()
    {
        new Thread(this).start();
    }

    public void run()
    {
        try
        {
            // 生成一个侦听端
            ServerSocketChannel ssc = ServerSocketChannel.open();
            // 将侦听端设为异步方式
            ssc.configureBlocking(false);
            // 生成一个信号监视器
            Selector s = Selector.open();
            // 侦听端绑定到一个端口
            ssc.socket().bind(new InetSocketAddress(port));
            // 设置侦听端所选的异步信号OP_ACCEPT
            ssc.register(s, SelectionKey.OP_ACCEPT);

            System.out.println("echo server has been set up ......");

            while (true)
            {
                int n = s.select();
                if (n == 0)
                {// 没有指定的I/O事件发生
                    continue;
                }
                Iterator it = s.selectedKeys().iterator();
                while (it.hasNext())
                {
                    SelectionKey key = (SelectionKey) it.next();
                    if (key.isAcceptable())
                    {// 侦听端信号触发
                        ServerSocketChannel server = (ServerSocketChannel) key
                            .channel();
                        // 接受一个新的连接
                        SocketChannel sc = server.accept();
                        sc.configureBlocking(false);
                        // 设置该socket的异步信号OP_READ:当socket可读时
                        // 触发函数DealwithData();
                        sc.register(s, SelectionKey.OP_READ);
                    }
                    if (key.isReadable())
                    {// 某socket可读信号
                        DealwithData(key);
                    }
                    it.remove();
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void DealwithData(SelectionKey key) throws IOException
    {
        int count = 0;
        // 由key获取指定socketchannel的引用
        SocketChannel sc = (SocketChannel) key.channel();
        r_buff.clear();
        // 读取数据到r_buff
        while ((count = sc.read(r_buff)) > 0);
        // 确保r_buff可读
        r_buff.flip();

        w_buff.clear();
        // 将r_buff内容拷入w_buff
        w_buff.put(r_buff);
        w_buff.flip();
        // 将数据返回给客户端
        EchoToClient(sc);

        w_buff.clear();
        r_buff.clear();
    }

    public void EchoToClient(SocketChannel sc) throws IOException
    {
        while (w_buff.hasRemaining())
            sc.write(w_buff);
    }

    public static void main(String args[])
    {
        if (args.length > 0)
        {
            port = Integer.parseInt(args[0]);
        }
        new AsyncServer();
    }
}

本地調試:

package test.nio.tcp;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
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 Administrator
 * @version
 */
public class NBTest
{


    /** Creates new NBTest */
    public NBTest()
    {
    }

    public void startServer() throws Exception
    {
        int channels = 0;
        int nKeys = 0;
        //使用Selector
        Selector selector = Selector.open();
        //建立Channel 并绑定到9000端口
        ServerSocketChannel ssc = ServerSocketChannel.open();
        System.out.println("Bind Host["+InetAddress.getLocalHost().getHostName()+"] Port["+7890+"]");
        InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(),7890);
        ssc.socket().bind(address);
        //使设定non-blocking的方式。
        ssc.configureBlocking(false);
        //向Selector注册Channel及我们有兴趣的事件
        SelectionKey s = ssc.register(selector, SelectionKey.OP_ACCEPT);
        printKeyInfo(s);
        while(true) // 不断的轮询
        {
            debug("NBTest: Starting select");
            //Selector通过select方法通知我们我们感兴趣的事件发生了。
            nKeys = selector.select();
            //如果有我们注册的事情发生了,它的传回值就会大于0
            if(nKeys > 0)
            {
                debug("NBTest: Number of keys after select operation: " +nKeys);
                //Selector传回一组SelectionKeys
                //我们从这些key中的channel()方法中取得我们刚刚注册的channel。
                Set selectedKeys = selector.selectedKeys();
                Iterator i = selectedKeys.iterator();
                while(i.hasNext())
                {
                    s = (SelectionKey) i.next();
                    printKeyInfo(s);
                    debug("NBTest: Nr Keys in selector: " +selector.keys().size());
                    //一个key被处理完成后,就都被从就绪关键字(ready keys)列表中除去
                    i.remove();
                    if(s.isAcceptable())
                    {
                        System.out.println("Receive a new socket.");
                        //从channel()中取得我们刚刚注册的channel。
                        Socket socket = ((ServerSocketChannel)s.channel()).accept().socket();
                        SocketChannel sc = socket.getChannel();       
                        sc.configureBlocking(false);
                        sc.register(selector, SelectionKey.OP_READ |SelectionKey.OP_WRITE);
                        System.out.println(++channels);
                    }
                    else
                    {
                        debug("NBTest: Channel not acceptable");
                    }
                }
            }
            else
            {
                debug("NBTest: Select finished without any keys.");
            }
        }
    }
   
    private static void debug(String s)
    {
        System.out.println(s);
    }


    private static void printKeyInfo(SelectionKey sk)
    {
        String s = new String();
        s = "Att: " + (sk.attachment() == null ? "no" : "yes");
        s += ", Read: " + sk.isReadable();
        s += ", Acpt: " + sk.isAcceptable();
        s += ", Cnct: " + sk.isConnectable();
        s += ", Wrt: " + sk.isWritable();
        s += ", Valid: " + sk.isValid();
        s += ", Ops: " + sk.interestOps();
        debug(s);
    }

    /**
     * @param args the command line arguments
     */
    public static void main (String args[])
    {
        NBTest nbTest = new NBTest();
        try
        {
            nbTest.startServer();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

}

 

 

分享到:
评论

相关推荐

    浅谈java中nio的使用方式

    Java NIO(New Input/Output)是一种用于处理I/O操作的非阻塞I/O模型,与传统的Java IO相比,它提供了更高的性能和更灵活的编程方式。NIO的核心概念包括Channel、Selector、SelectionKey和Buffer。 1. **Channel...

    浅谈Java的输入输出流

    尽管Java IO功能强大,但其实现方式有时会显得较为复杂,特别是当需要处理不同类型的输入输出时,往往需要使用到多个类和接口。本文将对Java输入输出流进行一次全面的介绍,旨在帮助初学者快速理解并掌握这一重要...

    浅谈Java中BIO、NIO和AIO的区别和应用场景

    Java中BIO、NIO和AIO的区别和应用场景 Java中IO模型有三种:BIO、NIO和AIO,下面我们来详细介绍它们的区别和应用场景。 BIO(Blocking I/O) BIO是Java中最古老的IO模型,它是同步并阻塞的。服务器的实现模式是一...

    浅谈Java堆外内存之突破JVM枷锁

    浅谈Java堆外内存之突破JVM枷锁 本文主要介绍了Java堆外内存的概念,包括JVM内存分配、JVM垃圾回收、堆外内存的垃圾回收等相关内容。Java开发者都知道,Java中不需要手动申请和释放内存,JVM会自动进行垃圾回收;而...

    浅谈tomcat一些细节配置

    【标题】:“浅谈Tomcat一些细节配置” Tomcat,作为Apache软件基金会的开源项目,是Java Servlet和JavaServer Pages(JSP)的容器,也是Java EE Web应用程序的标准实现。在实际开发和部署中,对Tomcat进行适当的...

    浅谈java中异步多线程超时导致的服务异常

    5. **优化任务执行**:尽量减少线程阻塞的时间,例如,避免长时间的IO操作,或者使用非阻塞的并发库如`java.nio`。 6. **监控与异常处理**:对线程池进行监控,记录线程的状态和执行情况,及时发现和处理异常,保证...

    浅谈Tomcat三种运行模式

    浅谈Tomcat三种运行模式 Tomcat服务器有三种运行模式:bio、nio和apr。每种模式都有其特点和优缺点,本文将对这三种模式进行详细的介绍。 bio模式 bio模式是Tomcat服务器的传统运行模式,也是Tomcat 7以下版本的...

    浅谈Linux 网络 I/O 模型简介(图文)

    Java网络编程中也有类似的概念,如BIO( Blocking I/O)、NIO(Non-blocking I/O)和AIO(Asynchronous I/O),它们分别对应上述模型的不同实现。其中,NIO和AIO在Java中提供了非阻塞和异步的网络通信能力,有助于...

    浅谈Android Studio导出javadoc文档操作及问题的解决

    "浅谈Android Studio导出javadoc文档操作及问题的解决" Android Studio是当前Android应用开发的主流IDE之一,但是在实际开发中,我们经常需要生成javadoc文档以便于其他开发者或团队成员了解我们的代码结构和设计...

    面试指南java

    - IO与NIO的区别:了解Java中传统IO和新IO(NIO)之间的区别,以及各自的使用场景。 - Synchronized和Lock的区别和用法:理解同步关键字synchronized和锁接口Lock的不同用法和优势。 - Final、Finally、Finalize的...

    2015Java面试指南

    - **Java实现浅克隆与深克隆**:浅克隆复制对象本身及含有引用的对象地址,而深克隆则复制了对象本身及所有成员变量的值。 - **枚举可以序列化吗**:枚举类型默认实现了`Serializable`接口,因此可以直接进行序列化...

    Java面试指南.pdf

    - **5.5 Java实现浅克隆与深克隆**:说明Java中克隆机制的两种形式及其应用场景。 - **5.6 枚举可以序列化吗**:探讨枚举类型的序列化可能性。 - **5.7 Java创建对象的方式**:列举并解释创建Java对象的各种方法。 -...

    JAVA面试指南

    - **5.5 Java实现浅克隆与深克隆:** - **浅克隆**复制对象本身及包含的引用类型成员变量,但不会复制这些引用的对象。 - **深克隆**复制对象本身及其引用的所有对象。 - **5.6 枚举可以序列化吗:** - 枚举类...

Global site tag (gtag.js) - Google Analytics