热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

netty中的传输

终于在课设的闲时间把netty实战的四五章给解决了这里来记录一下第四章里面所讲的IO首先说到IO,我想,必须要先了解阻塞,非阻塞,同步和异步这四个词看到一个讲的很易懂的例子:&am

终于在课设的闲时间把netty实战的四五章给解决了

这里来记录一下第四章里面所讲的IO

首先说到IO,我想,必须要先了解阻塞,非阻塞,同步和异步这四个词

看到一个讲的很易懂的例子:阻塞非阻塞同步异步

那么了解完这四个词,就到了IO了

传统的IO,即阻塞IO

也就是跟之前用socket编程那样,没有数据写入到来这边的线程就一直等待,直到数据到来然后再对数据进行处理,例如打印

拿出以前的老代码

public void bio(int port) throws IOException{
        final ServerSocket socket = new ServerSocket(port);
        try {
            //死循环,直到有连接再用线程将内容写入
            while (true){
                Socket client = socket.accept();//阻塞
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        OutputStream out;
                        try {
                            out = client.getOutputStream();
                            out.write("hello world".getBytes(CharsetUtil.UTF_8));
                            out.flush();
                            client.close();
                        }catch (IOException e){
                            e.printStackTrace();
                        }finally {
                            try {
                                client.close();
                            }catch (IOException e){
                                e.printStackTrace();
                            }
                        }
                    }
                }).start();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
传统阻塞IO

代码很容易懂,就是等客户端连接就往里面写入数据,每一个连接对应一个线程去处理,索性采用了多线程,如果是单线程,系统就会阻塞在这里,

多线程CPU在这里能释放做更多事情,的确是个很好的模型,至少我之前一直是这么觉得的...但是似乎这里忽略了一些问题,那就是连接数量的

问题,如果是小量的连接数还是好的,但是如果往大了增加连接数,打个比方一万,那么就会有一万个线程,那么问题就显而易见了,内存这上面就

已经有瓶颈了,而且,线程数量增大,线程之间的切换也会成为一个大问题,因为线程切换的成本很高,有可能线程切换的时间比执行的时间还长,

导致更严重的问题

所以可以知道的是,如果连接量小,那么这个模型是没问题的,如果大了,那么这个就无能为力了

 

再来说非阻塞IO,即NIO

这是netty实战上的非阻塞IO代码

public void serve(int port) throws IOException {
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);//channel设置为非阻塞模式
        ServerSocket ss = serverChannel.socket();
        InetSocketAddress address = new InetSocketAddress(port);
        ss.bind(address);
        Selector selector = Selector.open();
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        final ByteBuffer msg = ByteBuffer.wrap("Hi!\r\n".getBytes());
        for (;;){
            try {
                selector.select();//这个函数是阻塞的
            } catch (IOException ex) {
                ex.printStackTrace();
                //handle exception
                break;
            }
            Set readyKeys = selector.selectedKeys();
            Iterator iterator = readyKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                try {
                    if (key.isAcceptable()) {
                        ServerSocketChannel server =
                                (ServerSocketChannel) key.channel();
                        SocketChannel client = server.accept();
                        client.configureBlocking(false);
                        client.register(selector, SelectionKey.OP_WRITE |
                                SelectionKey.OP_READ, msg.duplicate());//注册到selector中
                        System.out.println(
                                "Accepted connection from " + client);
                    }
                    if (key.isWritable()) {
                        SocketChannel client =
                                (SocketChannel) key.channel();
                        ByteBuffer buffer =
                                (ByteBuffer) key.attachment();
                        while (buffer.hasRemaining()) {
                            if (client.write(buffer) == 0) {
                                break;
                            }
                        }
                        client.close();
                    }
                } catch (IOException ex) {
                    key.cancel();
                    try {
                        key.channel().close();
                    } catch (IOException cex) {
                        // ignore on close
                    }
                }
            }
        }
    }
View Code

注册当这几个事件到来的时候所对应的处理器。然后在合适的时机告诉事件选择器:对此事件感兴趣。对于写操作,就是写不出去的时候对

写事件感兴趣;对于读操作,就是完成连接和系统没有办法承载新读入的数据的时,对于accept,一般是服务器刚启动的时候;而对于connect,

一般是connect失败需要重连或者异步调用connect的时候,NIO的读写函数可以立刻返回,这就不用另开线程去等待结果了,如果一个连接不能读

写(socket.read()返回0或者socket.write()返回0),就把这件事记下来,记录的方式通常是在Selector上注册标记位,然后切换到其它就绪的连

接(channel)继续进行读写。

这样的优点:相比于阻塞模型,非阻塞不用再等待任务,而是把时间花费到其它任务上,也就是这个当前线程同时处理多个任务,但是也有缺点:

那就是导致任务完成的响应延迟增大了,因为每隔一段时间才去执行询问的动作,但是任务万一在两次询问之间的时间间隔内完成,就会导致整体

数据吞吐量的降低。影响用户体验

 

Netty中的阻塞和非阻塞

以上是java 里面的NIO,可以看到从阻塞改写到非阻塞这其中还是有很多地方要改的,势必会给带来很多麻烦,下面继续回到netty

而在netty中就不会出现这样的事情了,因为只需改变EventLoopGroup的种类,分别对应的OioEventLoopGroup和NioEventLoppGroup

和channel的种类,对应OioServerSocketChannel和NioServerSocketChannel,其余地方基本不变

 

Epool,专用于linux的本地非阻塞传输

jdk在linuxl中的NOI的实现上采用了不同的办法,就是使用了epoll调用,他有着比select和poll更好的性能,同时也是linux非阻塞网络编程的事实标准

而且如果程序是运行在linux,也不需要改动很多代码,就跟上面的例子一样,将NioEventLoopGroup和NioServerSocketChannel改成EpollEventLoopGroup

和EpollServerSocketChannel,这一改动在高负载的情况下能比NIO有更好的表现

 

JVM内部的传输

用于在同一个虚拟机中的客户端和服务端的通信,这个过程中的SocketAddress没有绑定具体的物理网络地址,只要服务器在运行,他就会存储在注册表里,channel关闭

即从表里注销,这里的传输不接收网络流量,其实也能猜出来,毕竟本地,所以他不能和其他我们使用的socket传输互相操作,所以如果客户端想使用本机,即同JVM中的服

务端就必须通过他实现

 

小结笔记:

IO访问过程:(网络IO本质上就是socket的读取)

 

 

 对于socket流,就是等待网络上的数据到达,然后复制到图中的缓冲区,然后复制到应用进程

 

 

 

 JVM内部通信还有其他几种IO那里还没来得及找例子做一做,找时间再补上,如果错误,还请多多指出


推荐阅读
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
author-avatar
生死有命富贵在天999_275
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有