`
sunlujing
  • 浏览: 180061 次
  • 性别: 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  
只有了解了过去的使用方式, 才知道现在方式对过去改进的地方。

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

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

相关推荐

    非阻塞式编程

    非阻塞式I/O在高并发服务器、网络编程、实时系统等领域有着广泛的应用,例如在开发高性能的Web服务器、数据库连接池以及网络通信软件时,非阻塞I/O可以显著提升系统处理能力。然而,它也增加了编程复杂性,因为程序...

    windows的阻塞和非阻塞Socket编程

    在Windows平台上进行网络编程时,Socket是至关重要的通信机制。Socket接口提供了丰富的API,使得开发者可以构建客户端和服务端应用程序,实现数据的传输。本篇主要关注的是Socket编程中的阻塞和非阻塞模式,这两种...

    java网络编程socket非阻塞通信

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

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

    在进行网络编程时,选择合适的通信模式取决于应用的需求。对于需要高效处理大量并发连接的场景,非阻塞模式与事件驱动编程是更好的选择。而对于简单且对实时性要求不高的应用,阻塞模式则相对易于实现。了解和掌握这...

    STM32H7 LWIP Rev非阻塞方式

    开发者可以通过分析和学习这个文件,更好地理解和应用STM32H7上的LWIP非阻塞网络通信。 总之,STM32H7结合LWIP的非阻塞方式,能够有效提高嵌入式设备的网络性能,同时降低CPU的闲置率,这对于需要高效处理网络请求...

    java点对点聊天(非阻塞式网络编程)

    首先,理解非阻塞网络编程的概念是至关重要的。在传统的阻塞I/O模型中,当一个线程尝试读取或写入数据时,如果数据尚未准备好,线程会进入等待状态,直到数据可用。这导致了资源的浪费,因为线程在等待期间无法执行...

    C++ socket 阻塞与非阻塞

    总结,C++ Socket编程中的阻塞与非阻塞模式选择取决于具体需求,如对实时性、响应速度或资源利用率的要求。多线程技术可以帮助提高服务器处理并发请求的能力,而定时清除连接资源则是保持服务器高效运行的重要策略。...

    网络编程高级应用 I/O阻塞与非阻塞操作应用

    在计算机网络编程中,I/O模型的选择对程序的性能和响应速度有着显著影响。本篇文章主要探讨了I/O阻塞与非阻塞操作的应用,以及socket多路复用技术,包括socket信号驱动、UDP广播与组播通信。这些概念和技术在开发高...

    Socket C++ TCP阻塞\非阻塞 服务器 客户端 开发

    ### Socket C++ TCP阻塞与非阻塞服务器客户端开发 #### 概述 本文档将详细介绍如何使用C++ Winsock库来开发TCP非阻塞服务器。通过本篇内容的学习,您将了解到设置socket函数为非阻塞模式的方法,并且能够深入了解...

    非阻塞TCP,VC2010,更新版

    非阻塞TCP编程是计算机网络通信中的一个重要概念,特别是在高并发和实时性要求较高的系统中。在传统的TCP编程中,通常使用阻塞模式,即一个线程在等待数据到达时会被挂起,直到数据到达才会继续执行。然而,这种模式...

    socket 多线程 例程 非阻塞模式

    Socket编程在IT领域中是网络通信的基础,尤其在C++编程环境下,利用VC++6.0这样的集成开发环境,开发者可以构建...通过对源代码的分析和实践,开发者能够提升自己的网络编程技能,为构建更复杂的网络应用打下坚实基础。

    非阻塞异步传输java网络编程(含源代码)

    ### 非阻塞异步传输Java网络编程 #### 实验背景及目标 本实验旨在通过Java语言实现一种基于自定义协议的文件传输系统,包括一个文件传输服务器(FileServer)和一个客户端(FileClient)。该系统的特点在于采用了非...

    Linux UDP socket 设置为的非阻塞模式与阻塞模式区别

    在进行网络编程时,我们经常会遇到阻塞模式与非阻塞模式的选择问题。这两种模式直接影响程序的运行效率和资源利用率。本文将详细介绍在Linux环境下,针对UDP Socket设置为非阻塞模式和阻塞模式的具体差异,以及它们...

    一站式学习Java网络编程 全面理解BIO:NIO:AIO1

    全面理解 Java 网络编程 - BIO、NIO、AIO 本课程旨在帮助学生全面理解 Java 网络编程中的 BIO、NIO、AIO 三剑客,掌握 RPC 编程的基础知识,并结合实战项目巩固所学。 一、网络编程三剑客 - BIO、NIO、AIO BIO...

    C++封装类CWSocket(多线程 非阻塞)

    非阻塞模式在网络编程中是一种重要的设计模式。在阻塞模式下,当一个socket调用(如recv或send)执行时,如果数据尚未准备好,那么程序会暂停,等待数据的到来。而在非阻塞模式下,这些函数会在没有数据可读或无法...

    MFC实现非阻塞Socket通信

    在IT领域,网络通信是不可或缺的一部分,而MFC(Microsoft Foundation Classes)库为Windows应用程序开发提供了强大的支持。...这个系统具有良好的可扩展性和性能,是现代网络编程的一个重要实践。

    异步 同步 阻塞 非阻塞 的说明_异步同步阻塞非阻塞_

    例如,在网络编程中,非阻塞I/O可以在数据没有完全到达时就返回,而不是等待所有数据到达。这种方式提高了效率,但需要更复杂的编程策略来处理可能的失败情况,如空读或空写。 **异步与阻塞/非阻塞的结合** 异步...

    异步非阻塞套接字Winsock开发网络通信程序开发入门

    对于初学者,使用MFC的CAsyncSocket类可以简化网络编程,因为它已经封装了异步非阻塞的功能。然而,为了深入理解这些概念,直接使用Winsock2 API是更推荐的方法。这样可以更好地掌握异步非阻塞套接字的工作原理。 ...

    Unix网络编程英文版PDF

    此外,书中还涉及到网络编程的高级主题,如多路复用技术、非阻塞套接字的使用、以及select和poll机制等。 第三版相较于第二版增加了很多新的内容,包括对IPv6的支持、新的网络编程APIs以及对多线程编程的讨论等。...

    feizuse.rar_C socket 非阻塞_网络服务_非阻塞_非阻塞 socket

    本压缩包中的资源聚焦于“非阻塞”模式的`socket`编程,这是一种高级网络编程技术,可以提高服务器的并发处理能力。 非阻塞`socket`是指当调用`recv()`或`send()`函数时,如果数据未准备好或者缓冲区满,不会使程序...

Global site tag (gtag.js) - Google Analytics