`
sunlujing
  • 浏览: 177925 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

我对非阻塞网络编程的理解

阅读更多

在传统的网络编程中我们依赖于ServerSocket,Socket进行通信,大致的框架就是ServerSocket调用accept方法,等待客户端的连接,如果连接进来的时候则创建一个服务器端socket,客户端和服务器端socket建立好InputStream 和outputStream通道进行通信,在这个网络IO的过程中inputStream的read 和outputStream的write方法都可能发送阻塞。为了减少这种阻塞对其他连接的影响,一般都会在服务器端为每个连接开辟一个新的线程,或者使用线程池技术来避免线程的创建销毁同时又一定程度支持并发量。然而这种情况下,如果发生大量的read 或者write阻塞线程池的效率会大大降低,而且操作系统也额外需要频繁的处理cpu的切换。阻塞式通信模式大致如下图所示。



 
 


非阻塞式通信实际是对上述模式的扩展,它的核心思想是为传统的socket加入事件监听的功能,操作系统可以在socket和serversocket上进行事件监听,一旦监听的对象发生了连接和可读可写的事件,监听器就会对注册了事件的对象返回相应的通知。在javaNIO中实现这一套的机制就是把socket 和ServerSocket重写成为SocketChanel,ServerSocketChanel,他们的底层仍然使用socket实现,所以原则上javaNIO包可以完全实现阻塞和非阻塞两种编程模式。事件监听的功能由Selection类完成,他使用select方法一直阻塞式监听注册了的事件是否发生,对于每一个发生的事件,他都会返回一个selectionKey,通过这个key我们就可以确定这个事件的发生源(socket)和相关信息。对于ServerSocketChanel,Socketchanel分别对应了不同的事件,serverChanel只有OP_ACCEPT代表是否可以接受连接,而socketChanel则有OP_CONNECT、read、write事件。笔者认为与阻塞IO相比他的优势在于可以避免read 和write的阻塞,因为这个比较具有实际意义的。比如是一个网络文件传输系统,read方法可能会因为网络原因发生多次阻塞,使用非阻塞IO read的话线程可以立即返回去处理其他任务。非阻塞式编程框架如下图所示


 
在具体的网络程序实现中,可以使用阻塞模式,也可以使用非阻塞或者混合模式。阻塞模式配合线程池技术实际上可以处理大部分发送小批量数据的需求,因为不会很频繁的发生read或者write阻塞,而是用非阻塞加线程池的技术对于发送大批量数据的程序则更有优势了。当然非阻塞式编程处理起来难道比较大,一方面对bytebuffer的操作相对繁琐,另一方面,某个数据的发送可能会触发多次的readable事件,这都需要在receive程序里进行额外编程来保证数据的完整性的。

 

  • 大小: 28.3 KB
  • 大小: 16.2 KB
5
2
分享到:
评论
15 楼 teasp 2013-05-08  
diggywang 写道
teasp 写道

你现在说的线程池和我认为的是一致的,但是你先前的“从线程池取线程”的说法难道不是很怪异吗?如果你线程池有5个线程,而连接数有10个,当然我是说阻塞模式的情况,那么你打算怎么弄?用5个线程处理10个连接,你是如何做到的?我只知道NIO可以。你用Java做tcp/ip设计?你说的是socket通信吧,难道Java能允许你在传输层的实现上做改动?


我承认我之前描述的有问题,在这里也不争论socket之类的东西。

回到起点:
teasp 写道

非阻塞才需要用线程池,阻塞模式如何用线程池?

阻塞模式下,5个线程处理10个连接怎么办?说白了,5个线程只能处理5个连接,但线程池的好处就是你还可以定义另外5个连接怎么处理,比如排队,丢弃。即使这样,效率也比不用线程池高很多。
非阻塞模式下,你可以不用线程池,多几个selector就行了,不过这样用比较极端,其实一个selector也是一个线程,充当了线程池的作用。实际使用一般都是1个或几个selector(不会超过5个),具体处理耗时业务逻辑的时候再用线程池。

在别人的帖子下争论这个不太好,以后有问题还是私信吧。




我相信楼主应该很乐意看到我们在这里讨论,实际上我有多年socket开发经验,也精通多线程,很多年以前使用的是自己实现的线程池。5个线程处理10个阻塞连接,你让剩下的5个排队?兄弟你是严肃的吗?我是真的很想看到阻塞模式下m个线程处理n个连接的代码。
14 楼 diggywang 2013-05-08  
teasp 写道

你现在说的线程池和我认为的是一致的,但是你先前的“从线程池取线程”的说法难道不是很怪异吗?如果你线程池有5个线程,而连接数有10个,当然我是说阻塞模式的情况,那么你打算怎么弄?用5个线程处理10个连接,你是如何做到的?我只知道NIO可以。你用Java做tcp/ip设计?你说的是socket通信吧,难道Java能允许你在传输层的实现上做改动?


我承认我之前描述的有问题,在这里也不争论socket之类的东西。

回到起点:
teasp 写道

非阻塞才需要用线程池,阻塞模式如何用线程池?

阻塞模式下,5个线程处理10个连接怎么办?说白了,5个线程只能处理5个连接,但线程池的好处就是你还可以定义另外5个连接怎么处理,比如排队,丢弃。即使这样,效率也比不用线程池高很多。
非阻塞模式下,你可以不用线程池,多几个selector就行了,不过这样用比较极端,其实一个selector也是一个线程,充当了线程池的作用。实际使用一般都是1个或几个selector(不会超过5个),具体处理耗时业务逻辑的时候再用线程池。

在别人的帖子下争论这个不太好,以后有问题还是私信吧。


13 楼 teasp 2013-05-08  
diggywang 写道
你说的线程池似乎是类似于连接池或者对象池之类的东西,说实话,我没见过。至少jdk里面的线程池是没法让你从线程池中获取线程的。可否演示下你是怎么使用线程池的?另外问个问题:你是否在工作中用Java做过socket通信?

如果你是初学者,我很乐意给你一步步解释;我从05年开始就做Java tcp/ip的设计,并有一套自己设计类似Netty的高性能Java NIO框架,在Akka,Hadoop等其它领域也摸爬滚打多年,所以我认为我的理解应该不会有太大的错误。
线程池的作用是让Runnable对象可以在已经存在的线程中运行而不必每次创建线程来执行,线程池虽然也是一类对象池,但和平常用的对象池(相信你用过最多的应该是数据库连接池)有些不同,像数据库连接池这样的对象池是从池中拿出对象,在让这些对象执行某些动作,如数据库查询什么的。线程池不关注你能否拿到线程,说实话你拿到了线程也没什么大的作用,线程池只需知道你想做什么,把需要做哪些事情定义在一个实现了Runnable接口的对象里,直接把这中对象扔给线程池,线程池会自动分配线程来执行这种Runnable对象。

代码我补贴了,Java最基础的东西。我想你应该在再次回复前在网络上搜索一遍。
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
http://technicalmumbojumbo.wordpress.com/2011/05/16/java-util-concurrent-executors-thread-pools-cache-fixed-scheduled-executorcompletionservice-tutorial/


如果你已经在编程道路上,尤其是在面向对象(非函数式编程)上走了多年,我建议你再拿出参考资料好好看看。


你现在说的线程池和我认为的是一致的,但是你先前的“从线程池取线程”的说法难道不是很怪异吗?如果你线程池有5个线程,而连接数有10个,当然我是说阻塞模式的情况,那么你打算怎么弄?用5个线程处理10个连接,你是如何做到的?我只知道NIO可以。你用Java做tcp/ip设计?你说的是socket通信吧,难道Java能允许你在传输层的实现上做改动?
12 楼 diggywang 2013-05-07  
你说的线程池似乎是类似于连接池或者对象池之类的东西,说实话,我没见过。至少jdk里面的线程池是没法让你从线程池中获取线程的。可否演示下你是怎么使用线程池的?另外问个问题:你是否在工作中用Java做过socket通信?

如果你是初学者,我很乐意给你一步步解释;我从05年开始就做Java tcp/ip的设计,并有一套自己设计类似Netty的高性能Java NIO框架,在Akka,Hadoop等其它领域也摸爬滚打多年,所以我认为我的理解应该不会有太大的错误。
线程池的作用是让Runnable对象可以在已经存在的线程中运行而不必每次创建线程来执行,线程池虽然也是一类对象池,但和平常用的对象池(相信你用过最多的应该是数据库连接池)有些不同,像数据库连接池这样的对象池是从池中拿出对象,在让这些对象执行某些动作,如数据库查询什么的。线程池不关注你能否拿到线程,说实话你拿到了线程也没什么大的作用,线程池只需知道你想做什么,把需要做哪些事情定义在一个实现了Runnable接口的对象里,直接把这中对象扔给线程池,线程池会自动分配线程来执行这种Runnable对象。

代码我补贴了,Java最基础的东西。我想你应该在再次回复前在网络上搜索一遍。
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
http://technicalmumbojumbo.wordpress.com/2011/05/16/java-util-concurrent-executors-thread-pools-cache-fixed-scheduled-executorcompletionservice-tutorial/


如果你已经在编程道路上,尤其是在面向对象(非函数式编程)上走了多年,我建议你再拿出参考资料好好看看。
11 楼 teasp 2013-05-07  
diggywang 写道
teasp 写道
diggywang 写道
teasp 写道
楼主似乎说反了。大批量数据的情况下,阻塞模式更为有效。非阻塞的优势在于处理大并发连接,或者数据量不多时开销更小。非阻塞才需要用线程池,阻塞模式如何用线程池?

阻塞模式不用线程池的话,永远只能同时处理一个连接请求。


我不理解你说的连接请求的意思,是指建立连接,还是就是处理连接本身? 如果是前者,非阻塞也永远只能同时处理一个连接请求;如果是后者,那就十分奇怪,阻塞模式需要一个连接配一个线程进行阻塞读取,怎么都是多线程的,你如何把它做成单线程的?这也是我为什么会觉得阻塞模式使用线程池很怪。如果可以的话,不妨贴点代码分享下。说实在的,我实在想象不出来如何用m个线程处理n个阻塞模式下的连接,但是非阻塞就可以。


你自己都说了--“阻塞模式需要一个连接配一个线程进行阻塞读取,怎么都是多线程的”。这个线程怎么来的,当然是从线程池你获取来的,当然,你也可以自己对每个连接单独创建线程。


你说的线程池似乎是类似于连接池或者对象池之类的东西,说实话,我没见过。至少jdk里面的线程池是没法让你从线程池中获取线程的。可否演示下你是怎么使用线程池的?另外问个问题:你是否在工作中用Java做过socket通信?
10 楼 diggywang 2013-05-07  
teasp 写道
diggywang 写道
teasp 写道
楼主似乎说反了。大批量数据的情况下,阻塞模式更为有效。非阻塞的优势在于处理大并发连接,或者数据量不多时开销更小。非阻塞才需要用线程池,阻塞模式如何用线程池?

阻塞模式不用线程池的话,永远只能同时处理一个连接请求。


我不理解你说的连接请求的意思,是指建立连接,还是就是处理连接本身? 如果是前者,非阻塞也永远只能同时处理一个连接请求;如果是后者,那就十分奇怪,阻塞模式需要一个连接配一个线程进行阻塞读取,怎么都是多线程的,你如何把它做成单线程的?这也是我为什么会觉得阻塞模式使用线程池很怪。如果可以的话,不妨贴点代码分享下。说实在的,我实在想象不出来如何用m个线程处理n个阻塞模式下的连接,但是非阻塞就可以。


你自己都说了--“阻塞模式需要一个连接配一个线程进行阻塞读取,怎么都是多线程的”。这个线程怎么来的,当然是从线程池你获取来的,当然,你也可以自己对每个连接单独创建线程。
9 楼 teasp 2013-05-06  
sunlujing 写道
teasp 写道
楼主似乎说反了。大批量数据的情况下,阻塞模式更为有效。非阻塞的优势在于处理大并发连接,或者数据量不多时开销更小。非阻塞才需要用线程池,阻塞模式如何用线程池?

我觉得应该是你弄反了吧~

你有阻塞模式使用线程池处理连接的例子吗?可否参考下?
8 楼 teasp 2013-05-06  
diggywang 写道
teasp 写道
楼主似乎说反了。大批量数据的情况下,阻塞模式更为有效。非阻塞的优势在于处理大并发连接,或者数据量不多时开销更小。非阻塞才需要用线程池,阻塞模式如何用线程池?

阻塞模式不用线程池的话,永远只能同时处理一个连接请求。


我不理解你说的连接请求的意思,是指建立连接,还是就是处理连接本身? 如果是前者,非阻塞也永远只能同时处理一个连接请求;如果是后者,那就十分奇怪,阻塞模式需要一个连接配一个线程进行阻塞读取,怎么都是多线程的,你如何把它做成单线程的?这也是我为什么会觉得阻塞模式使用线程池很怪。如果可以的话,不妨贴点代码分享下。说实在的,我实在想象不出来如何用m个线程处理n个阻塞模式下的连接,但是非阻塞就可以。
7 楼 sunlujing 2013-05-03  
teasp 写道
楼主似乎说反了。大批量数据的情况下,阻塞模式更为有效。非阻塞的优势在于处理大并发连接,或者数据量不多时开销更小。非阻塞才需要用线程池,阻塞模式如何用线程池?

我觉得应该是你弄反了吧~
6 楼 diggywang 2013-05-03  
teasp 写道
楼主似乎说反了。大批量数据的情况下,阻塞模式更为有效。非阻塞的优势在于处理大并发连接,或者数据量不多时开销更小。非阻塞才需要用线程池,阻塞模式如何用线程池?

阻塞模式不用线程池的话,永远只能同时处理一个连接请求。
5 楼 teasp 2013-05-03  
楼主似乎说反了。大批量数据的情况下,阻塞模式更为有效。非阻塞的优势在于处理大并发连接,或者数据量不多时开销更小。非阻塞才需要用线程池,阻塞模式如何用线程池?
4 楼 javay 2013-05-03  
sunlujing 写道
netkiller.github.com 写道
找一本80年c语言书 里面都讲得很清楚。

恩,你想表达啥啊
两种意思。不是手里砸了一些书就是指现在的书过于浮躁不注重基础了。
3 楼 sunlujing 2013-05-02  
netkiller.github.com 写道
找一本80年c语言书 里面都讲得很清楚。

恩,你想表达啥啊
2 楼 netkiller.github.com 2013-05-02  
找一本80年c语言书 里面都讲得很清楚。
1 楼 robert.wei 2013-05-02  
只有了解了过去的使用方式, 才知道现在方式对过去改进的地方。

阻塞模式,或非阻塞模式, 其实对于单次的网络通信的效率并不会发生影响。但是非阻塞模式模式能让你服务端在单次通讯阻塞的情况下,处理其他的事情。这样整个并发量就上去了。

解决这个的核心思想: 就是观察者模式的应用。

相关推荐

    java网络编程socket非阻塞通信

    通过java网络编程深入理解socket阻塞通信和非阻塞通信的在网络中的应用 源码包每一行都有注释,在代码里面每一个类都有详细的注释来解释这个类的功能这个方法的功能,调用哪一个类的哪一个功能等等。 压缩包包含实验...

    QTcpSocket通信编程时阻塞与非阻塞的问题 - findumars - 博客园1

    1. 编程理解(36) 1. 经典资料(15) 1. 开源项目(16) 9.SaaS-云存储,云服务(38) 9.SaaS-云计算-学习(38)

    阻塞与非阻塞

    最近帮一哥们做一个简单的通信演示小程序,重拾遗忘很久的Windows网络编程,通过此次演示程序的制作,对于TCP的三路握手、Socket的运用理解更加深入了,同时从文字上的阻塞与非阻塞到情真意切的感受到二者之间的差异...

    最新C++网络编程实践视频教程 陈硕

    1.网络编程概要.mkv2.一个TCP的简单实验.mkv3.课程内容大纲.mkv4.回顾基础的Sockets API.mkv5.TTCP代码概览.mkv6.使用TTCP进行网络传输性能测试.mkv7.阻塞IO下的TTCP实验.mkv8.TCP自连接.mkv9.扩展练习.mkv10.时钟...

    UNIX网络编程卷2进程间通信

    本书是一部UNIX网络API的经典之作!...I/O:复用高级函数,非阻塞和信号驱动 守护进程和inetd UNIX域协议 ioctl操作 广播和组播 线程 流 设计:TCP迭代的、并发的、预先创建的和预先线程化的服务器

    java网络编程http通信

    通过java网络编程深入理解http非阻塞通信和阻塞通信,以及http协议在网络中的应用 源码包每一行都有注释,在代码里面每一个类都有详细的注释来解释这个类的功能这个方法的功能,调用哪一个类的哪一个功能等等。 压缩...

    MFC网络编程之自制浏览器

     对于这些概念,初学者的理解也许只能似是而非,我将用一个最简单的例子说明异步非阻塞Socket的基本原理和工作机制。目的是让初学者不仅对Socket异步非阻塞的概念有个非常透彻的理解,而且也给他们提供一个用Socket...

    同步、异步、阻塞和非阻塞的概念

    在进行网络编程时,我们常常见到同步、异步、阻塞和非阻塞四种调用方式。这些方式彼此概念并不好理解。下面是我对这些术语的理解。 同步 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。...

    UNIX网络编程卷1套接字联网API.part1.rar

    本书是一部UNIX网络API的经典之作!...I/O:复用高级函数,非阻塞和信号驱动 守护进程和inetd UNIX域协议 ioctl操作 广播和组播 线程 流 设计:TCP迭代的、并发的、预先创建的和预先线程化的服务器

    UNIX网络编程卷1套接字联网API.part2.rar

    本书是一部UNIX网络API的经典之作!...I/O:复用高级函数,非阻塞和信号驱动 守护进程和inetd UNIX域协议 ioctl操作 广播和组播 线程 流 设计:TCP迭代的、并发的、预先创建的和预先线程化的服务器

    详解socket阻塞与非阻塞,同步与异步、I/O模型

    在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步: 所谓同步,就是在c端发出一个功能调用时,在没有得到结果之前,该调用就不返回...

    linux 网络编程源代码

    1.1 网络的历史.......................................................................................................1 1.2 OSI 模型........................................................................

    精通Windows Sockets网络开发:基于Visual C++实现PDF和源代码

    全书内容包括准备开发环境、TCP/IP基本介绍、Windows套接字基础、协议特征、基本TCP套接字编程、基本UDP套接字编程、套接字选项、套接字阻塞模式开发、套接字非阻塞模式开发、Select模型开发、WSAAsyncSelect模型...

    Java网络编程(第三版)中文版.part11.rar

    “直到找到这本书之后,我才开始理解Java网络编程。” ——Bruce Eckel,《Thinking in Java》的作者 内容简介回到顶部↑《Java网络编程》第三版会为你介绍Java网络API的最新特性。本书讨论了JDK 1.4和1.5(现在已...

    UNIX网络编程卷2进程间通信(第2版)

    进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机间网络应用程序的必要条件。本书从对Posix IPC和System V IPC的内部结构开始讨论,全面深入地介绍了4种IPC形式:消息传递(管道、...

    Java网络编程(第三版)中文版.part06.rar

    “直到找到这本书之后,我才开始理解Java网络编程。” ——Bruce Eckel,《Thinking in Java》的作者 内容简介回到顶部↑《Java网络编程》第三版会为你介绍Java网络API的最新特性。本书讨论了JDK 1.4和1.5(现在已...

    Windows Sockets网络编程 总计4个包,part2

    它结合大量示例,对WindowsSockets规范进行了深刻地解读,系统讲解了WindowsSockets网络编程及其相关的概念、原理、主要命令、操作模式,以及开发技巧和可能的陷阱,从程序员的角度给出了大量的建议和最佳实践,是...

    Java网络编程(第三版)中文版.part07.rar

    “直到找到这本书之后,我才开始理解Java网络编程。” ——Bruce Eckel,《Thinking in Java》的作者 内容简介回到顶部↑《Java网络编程》第三版会为你介绍Java网络API的最新特性。本书讨论了JDK 1.4和1.5(现在已...

    Java网络编程(第三版)中文版.part09.rar

    “直到找到这本书之后,我才开始理解Java网络编程。” ——Bruce Eckel,《Thinking in Java》的作者 内容简介回到顶部↑《Java网络编程》第三版会为你介绍Java网络API的最新特性。本书讨论了JDK 1.4和1.5(现在已...

    Java网络编程(第三版)中文版.part01.rar

    “直到找到这本书之后,我才开始理解Java网络编程。” ——Bruce Eckel,《Thinking in Java》的作者 内容简介回到顶部↑《Java网络编程》第三版会为你介绍Java网络API的最新特性。本书讨论了JDK 1.4和1.5(现在已...

Global site tag (gtag.js) - Google Analytics