/**
 * Created by LiuHuiChao on 2016/11/15.
 * description:based on TCP/IP+NIO to deliver the message
 */
public class TCP_IP_NIO {

    @Test
    public void clientStart() throws IOException {
        SocketChannel channel=SocketChannel.open();
        channel.configureBlocking(false);//设置为非阻塞方式
        SocketAddress remote=new InetSocketAddress("127.0.0.1",8888);
        channel.connect(remote);
        Selector selector= Selector.open();
        channel.register(selector, SelectionKey.OP_CONNECT);
        /**阻塞至有感兴趣的IO事件发生,或到达超时时间,如果希望一直等至有感兴趣的IO事件发生,可调用无参数select方法,
         * 如果希望不阻塞直接返回目前是否有感兴趣的事件发生,可以调用selectNow方法
         * */
        int nkeys=selector.select();//如果nkeys大于0,说明有感兴趣的IO事件发生
        SelectionKey selectionKey=null;
        if(nkeys>0){
            Set<SelectionKey> keys=selector.selectedKeys();
            for(SelectionKey key : keys){
                //对于发生连接的事件
                if(key.isConnectable()){
                    SocketChannel sc= (SocketChannel) key.channel();
                    sc.configureBlocking(false);
                    /**注册感兴趣的IO读事件,通常不直接注册写事件,在发送缓冲区未满的情况下,一直是可写的,
                     * 因此,如注册了写事件,而又不用写数据,很容易造成CUP消耗100%的情况;
                     * */
                    selectionKey=sc.register(selector,SelectionKey.OP_READ);
                    sc.finishConnect();
                }else if(key.isReadable()){/**有流可读*/
                    ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
                    SocketChannel sc= (SocketChannel) key.channel();
                    int readBytes=0;
                    try{
                        int ret=0;
                        try{
                            /**读取目前可读的流,sc.read返回的为成功复制到bytebuffer中的字节数;
                             * 此步骤为阻塞操作,值可能为0;当已经是流的结尾时,返回-1
                             * */
                            while((ret=sc.read(byteBuffer))>0){
                                readBytes+=ret;
                            }
                        }finally{
                            byteBuffer.flip();
                        }
                    }finally{
                        if(byteBuffer!=null){
                            byteBuffer.clear();
                        }
                    }
                }else if(key.isWritable()){/**可写入流*/
                    //取消对OP_WRITE事件的注册
                    key.interestOps(key.interestOps()&(~selectionKey.OP_WRITE));
                    SocketChannel sc= (SocketChannel) key.channel();
                    /**此步骤为阻塞操作,直到写入操作系统发送缓冲区或网路IO出现异常,返回的为成功写入的字节数,当操作系统的发送缓冲区已满,此处返回0*/
                    ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
                    sc.read(byteBuffer);
                    int writtenedSize=sc.write(byteBuffer);
                    //如未写入,则继续注册感兴趣的OP_WRITE事件
                    if(writtenedSize==0){
                        key.interestOps(key.interestOps() | selectionKey.OP_WRITE);
                    }
                }
            }
            selector.selectedKeys().clear();
        }

    }

    @Test
    public void serverStart() throws IOException {
        ServerSocketChannel ssc=ServerSocketChannel.open();
        ServerSocket serverSocket=ssc.socket();
        //绑定要监听的端口
        serverSocket.bind(new InetSocketAddress(8888));
        ssc.configureBlocking(false);
        Selector selector= Selector.open();
        //注册感兴趣的事件连接
        ssc.register(selector,SelectionKey.OP_ACCEPT);
        /**
         * 之后采取和客户端相同的方式对selector.select进行轮询。。。但是要增加一个key.isAcceptable的处理。。。
         * */

    }
}

Java——基于java自身包实现消息系统间的通信(TCP/IP+NIO)的更多相关文章

  1. Java——基于java自身包实现消息系统间的通信(TCP/IP+BIO)

    最近看到阿里的一位童鞋写的一本关于分布式的书,感觉不错,准备把这本书上基础的代码都写一写. /** * Created by LiuHuiChao on 2016/11/15. * descripti ...

  2. Java多线程之线程的状态以及线程间协作通信导致的线程状态转换

      转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6561589.html  一:线程的状态以及变化图 Java中线程中状态可分为五种:New(新建状态),Ru ...

  3. 《Wireshark数据包分析实战》 - http背后,tcp/ip抓包分析

    作为网络开发人员,使用fiddler无疑是最好的选择,方便易用功能强. 但是什么作为爱学习的同学,是不应该止步于http协议的,学习wireshark则可以满足这方面的需求.wireshark作为抓取 ...

  4. Java基于SSM的个人博客系统(源码 包含前后台)

    @ 目录 系统简介 系统运行截图 核心代码 写在最后 系统简介 技术点:Java.JSP.SSM框架,实现了个人博客系统 用户角色分为:普通用户.管理员.系统管理员 功能:发博客.博客分类.博客删除. ...

  5. Java并发读书笔记:如何实现线程间正确通信

    目录 一.synchronized 与 volatile 二.等待/通知机制 等待 通知 面试常问的几个问题 sleep方法和wait方法的区别 关于放弃对象监视器 三.等待通知典型 生产者消费者模型 ...

  6. Java通过wait()和notifyAll()方法实现线程间的通信

    Java代码(使用了2个内部类): package Threads; import java.util.LinkedList; /** * Created by Frank */ public cla ...

  7. Java核心知识点学习----多线程并发之线程间的通信,notify,wait

    1.需求: 子线程循环10次,主线程循环100次,这样间隔循环50次. 2.实现: package com.amos.concurrent; /** * @ClassName: ThreadSynch ...

  8. 分布式架构从零开始========》【基于Java自身技术实现消息方式的系统间通信】

    基于Java自身包实现消息方式的系统间通信的方式有:TCP/IP+BIO,TCP/IP+NIO,UDP/IP+BIO,UDP/IP+NIO.下面就这4种类型一一做个详细的介绍: 一.TCP/IP+BI ...

  9. Java与C++进行系统间交互:Protocol Buffer

    在一次项目中,因笔者负责的java端应用需要与公司C++系统进行交互,公司选定Protocol Buffer方案,故简单的了解一下 有需要的可以看一下其他作者的文章,了解一下Protobuf: htt ...

随机推荐

  1. Windows7下安装配置PostgreSQL10

    PostgreSQL安装: 一.windows7下安装过程首先上PostgreSQL官方网站的下载页面https://www.postgresql.org/download/windows/,下载本软 ...

  2. 2424. [HAOI2010]订货【费用流】

    Description 某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为 ...

  3. .net中使用mysql回滚和sqlserver回滚的区别

    关于sqlserver事务和mysql事务 首先这是一种方法 public static int GetExecteQuery()        {            SqlConnection ...

  4. C# - 静态类和静态构造函数

    一个类只能有一个静态构造函数,该构造函数不能有访问修饰符,不能带任何参数,不能直接调用,只能在: 1 创建包含静态构造函数的类实例时 2 访问包含静态构造函数的静态成员时 会先调用静态构造函数,无论创 ...

  5. Spring @Value 默认值

    @Value(value = "${etl.maxthreadcount:3}") private long MaxThreadCount;

  6. HDU 1711 Number Sequence (KMP简单题)

    Number Sequence Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  7. HDU 1158(非常好的锻炼DP思维的题目,非常经典)

    题目链接: acm.hdu.edu.cn/showproblem.php?pid=1158 Employment Planning Time Limit: 2000/1000 MS (Java/Oth ...

  8. nyoi 42(欧拉回路)

    http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=42 一笔画问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 ...

  9. Oracle Enterprise Linux 64-bit 下Oracle11g的监听配置改动及測试步骤

    測试环境:Oracle Enterprise Linux 64-bit (5.8版本号) + Oracle 11g 64位 相关说明: Oracle11g64位软件的安装位置为/u01/app/ora ...

  10. 开源Webshell利用工具——Altman

    开源Webshell利用工具--Altman keepwn @ 工具 2014-06-04 共 6114 人围观,发现 43 个不明物体收藏该文 Altman,the webshell tool,自己 ...