1      非阻塞(Nonblocking)体系结构

在这一部分,我将从理论的角度来解释非阻塞体系的结构及其工作原理。这部“喜剧”(当然,如果你喜欢的话也可以称做戏剧)的“人物”如下:

●服务器端:接收请求的应用程序。

●客户端:向服务器端发出请求的应用程序。

●套接字通道:客户端与服务器端之间的通信通道。它能识别服务器端的IP地址和端口号。数据以Buffer中元素的形式通过套接字通道传送。

●选择器:所有非阻塞技术的主要对象。它监视着已注册的套接字通道,并序列化服务器需要应答的请求。

●关键字:选择器用来对对象的请求进行排序。每个关键字代表一个单独的客户端子请求并包含识别客户端和请求类型的信息。

2 SocketChannel 类

SocketAddress rama = new SocketAddress("localhost" , 8888) ;

利用静态工厂方法得到SocketChannel的实例。

SocketChannel client = SocketChannel.open(rama) ;

如果这是传统的套接字,那么就会寻求得到socket的输入或者输出流,利用通道,我们可以直接写入通道本身,

不是写入字节数组,而是要写入ByteBuffer对象,将此对象写入 client的read 方法。

客户端应用程序同时执行对服务器端的请求,接着选择器将其集中起来,创建关键字,然后将其发

送至服务器端。这看起来像是阻塞(Blocking)体系,因为在一定时间内只处理一个请求,但事实并非如此。

实际上,每个关键字不代表从客户端发至服务器端的整个信息流,仅仅只是一部分。我们不要忘了选择器能

分割那些被关键字标识的子请求里的数据。因此,如果有更多连续地数据发送至服务器端,那么选择器就会

创建更多的根据时间共享策略(Time-sharing policy)来进行处理的关键字。强调一下,在图一中关键字的颜色

与客户端的颜色相对应。

服务器端非阻塞(Server Nonblocking)

客户端和服务器端是两个Java应用程序。套接字通道是SocketChannel类的实例,这个类允许通过网络传送数据。

它们能被Java程序员看作是一个新的套接字。SocketChannel类被定义在java.nio.channel包中。

选择器是一个Selector类的对象。该类的每个实例均能监视更多的套接字通道,进而建立更多的连接。

当一些有意义的事发生在通道上(如客户端试图连接服务器端或进行读/写操作),选择器便会通知应用程序处理请求。

选择器会创建一个关键字,这个关键字是SelectionKey类的一个实例。每个关键字都保存着应用程序的标识及请求的类型。

其中,请求的类型可以是如下之一:

基本上,服务器端的实现是由选择器等待事件和创建关键字的无限循环组成的。根据关键字的类型,及时的执行操作。

关键字存在以下4种可能的类型。

Acceptable: 相应的客户端要求连接。

Connectable:服务器端接受连接。

Readable:服务器端可读。

Writeable:服务器端可写。

一个通用的实现非阻塞服务器的算法如下:

create SocketChannel;

create Selector

associate the SocketChannel to the Selector

for(;;) {

waiting events from the Selector;

event arrived; create keys;

for each key created by Selector {

check the type of request;

isAcceptable:

get the client SocketChannel;

associate that SocketChannel to the Selector;

record it for read/write operations

continue;

isReadable:

get the client SocketChannel;

read from the socket;

continue;

isWriteable:

get the client SocketChannel;

write on the socket;

continue;

}

}

3  下面为一个实例

(1)客户端

1

packagecn.bupt.channel;23importjava.io.IOException;4importjava.net.InetSocketAddress;5importjava.net.SocketAddress;6importjava.nio.ByteBuffer;7importjava.nio.channels.Channels;8importjava.nio.channels.SocketChannel;9importjava.nio.channels.WritableByteChannel;1011importcn.bupt.constant.Default;1213

publicclassChargenClient{1415publicstaticintDEFAULT_PORT=8778;16

/** *//**17     *@paramargs18*/19

publicstaticvoidmain(String[] args){20//TODO Auto-generated method stub21if(args.length==0)22

{23           System.out.println("please input the port");24return;25       }2627intport ;282930       port=DEFAULT_PORT ;3132       SocketAddress address=newInetSocketAddress(args[0] , port) ;33

try{34        SocketChannel client=SocketChannel.open(address) ;35        ByteBuffer buffer=ByteBuffer.allocate(74) ;36        WritableByteChannel out=Channels.newChannel(System.out) ;3738while(client.read(buffer)!=-1)39

{40            buffer.flip() ;41            out.write(buffer) ;42            buffer.clear() ;4344        }45464748495051

    }catch(IOException e){52//TODO Auto-generated catch block53e.printStackTrace();54    }55565758    }5960}61

(2) 服务器端

1

packagecn.bupt.channel;23importjava.io.IOException;4importjava.net.InetSocketAddress;5importjava.net.ServerSocket;6importjava.nio.ByteBuffer;7importjava.nio.channels.SelectionKey;8importjava.nio.channels.Selector;9importjava.nio.channels.ServerSocketChannel;10importjava.nio.channels.SocketChannel;11importjava.util.Iterator;12importjava.util.Set;1314

publicclassChargenServer{1516publicstaticfinalintDEFAULT_PORT=8778;17

/** *//**18     *@paramargs19*/20

publicstaticvoidmain(String[] args){21//TODO Auto-generated method stub22intport ;23        port=DEFAULT_PORT ;2425byte[] rotation=newbyte[95*2] ;26for(bytei=''; i

{28            rotation[i-'']=i ;29            rotation[i+95-'']=i ;30        }3132        ServerSocketChannel serverChannel=null;33        Selector selector=null;343536

/** *//**37         * 先建立服务器端的通道38         *39*/4041

try{42            serverChannel=ServerSocketChannel.open() ;43            ServerSocket ss=serverChannel.socket() ;44            InetSocketAddress address=newInetSocketAddress(port) ;45            ss.bind(address) ;46            serverChannel.configureBlocking(false) ;47            selector=Selector.open() ;48            serverChannel.register(selector, SelectionKey.OP_ACCEPT) ;49505152

        }catch(IOException e){53//TODO Auto-generated catch block54e.printStackTrace();55        }565758while(true)59

{6061

try{62                selector.select() ;63

            }catch(IOException e){64                e.printStackTrace();65            }6667            Set readyKeys=selector.selectedKeys() ;68            Iterator iter=readyKeys.iterator() ;69while(iter.hasNext())70

{71                SelectionKey key=(SelectionKey) iter.next() ;72                iter.remove() ;7374if(key.isAcceptable())75

{76                    ServerSocketChannel server=(ServerSocketChannel) key.channel() ;77

try{78                        SocketChannel client=server.accept() ;79                        System.out.println("Accept connection from"+client) ;80                        client.configureBlocking(false) ;81                        SelectionKey key2=client.register(selector, SelectionKey.OP_WRITE) ;82                        ByteBuffer buffer=ByteBuffer.allocate(74) ;83                        buffer.put(rotation ,0,72) ;84                        buffer.put((byte)'\r') ;85                        buffer.put((byte)'\n') ;86                        buffer.flip() ;87                        key2.attach(buffer) ;8889909192

                    }catch(IOException e){93//TODO Auto-generated catch block94e.printStackTrace();95                    }96979899100                }101102else103if(key.isWritable())104

{105106

/** *//**107                         * 建立客户端通道108                         *109*/110                        SocketChannel client=(SocketChannel)key.channel() ;111                        ByteBuffer buffer=(ByteBuffer) key.attachment() ;112if(!buffer.hasRemaining())113

{114                            buffer.rewind() ;115intfirst=buffer.get() ;116                            buffer.rewind() ;117intposition=first-''+1;118                            buffer.put(rotation , position ,72) ;119                            buffer.put((byte)'\r') ;120                            buffer.put((byte)'\n');121                            buffer.flip() ;122                        }123

try{124                            client.write(buffer) ;125

                        }catch(IOException e){126//TODO Auto-generated catch block127e.printStackTrace();128                        }129                    }130131132133134135136137138                key.cancel() ;139

try{140                    key.channel().close() ;141

                }catch(IOException e){142//TODO Auto-generated catch block143e.printStackTrace();144                }145            }146147148        }149150151152153154155156157158    }159160}161

posted on 2010-08-01 21:19 buptduming 阅读(4114) 评论(0)  编辑  收藏

java 阻塞 socket_java socket非阻塞I/O相关推荐

  1. java非阻塞io流_阻塞式和非阻塞io流初认识

    1  什么是阻塞式和非阻塞式? 阻塞式IO:IO即input/output,阻塞式IO指的是"一旦输入/输出工作没有完成,则程序阻塞,直到输入/输出工作完成".在目前,我们从书本上 ...

  2. java merlin_Merlin 给 Java 平台带来了非阻塞 I/O

    新增的功能大幅降低了线程开销 Java 技术平台早就应该提供非阻塞 I/O 机制了.幸运的是,Merlin(JDK 1.4)有一根几乎在各个场合都适用的魔杖,而解除阻塞了的 I/O 的阻塞状态正是这位 ...

  3. [转载]Merlin 给 Java 平台带来了非阻塞 I/O

    Merlin 给 Java 平台带来了非阻塞 I/O Java 技术平台早就应该提供非阻塞 I/O 机制了.幸运的是,Merlin(JDK 1.4)有一根几乎在各个场合都适用的魔杖,而解除阻塞了的 I ...

  4. java之阻塞队列和非阻塞队列

    目录 一.什么是阻塞队列 二.阻塞队列种类分析 三.非阻塞队列 Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子 ...

  5. boost库之socket 非阻塞/缓冲区大小等属性设置

    boost库之socket 非阻塞/缓冲区大小等属性设置 原文:http://blog.csdn.net/byxdaz/article/details/77318219 asio socket 非阻塞 ...

  6. php socket非阻塞,php stream_set_blocking设置非阻塞模式,php stream_set_blocking影响函数fgets()和fread()...

    stream_set_blocking函数可以将资源流设置为阻塞模式或者非阻塞模式,主要影响的函数分别是fgets,fread,其他的手册没有说. 在socket编程中,如果一个socket连接上了, ...

  7. 同步阻塞、同步非阻塞、异步阻塞、异步非阻塞与 I/O 多路复用、Java NIO 之间的联系

    同步阻塞.同步非阻塞.异步阻塞.异步非阻塞与 I/O 多路复用.Java NIO 之间的联系 先验知识 此处的异步指的是什么 同步.异步.阻塞.非阻塞 同步阻塞.同步非阻塞.异步阻塞.异步非阻塞 一个 ...

  8. socket的阻塞模式和非阻塞模式(send和recv函数在阻塞和非阻塞模式下的表现)

    socket的阻塞模式和非阻塞模式 无论是Windows还是Linux,默认创建socket都是阻塞模式的 在Linux中,可以再创建socket是直接将它设置为非阻塞模式 int socket (i ...

  9. socket的阻塞模式和非阻塞模式

    文章目录 socket的阻塞模式和非阻塞模式 如何将socket设置为非阻塞模式 send和recv函数在阻塞和非阻塞模式下的表现 非阻塞模式下send和recv函数的返回值总结 阻塞与非阻塞sock ...

最新文章

  1. YOLOX——Win10下训练自定义VOC数据集
  2. storm kafkaSpout 踩坑问题记录! offset问题!
  3. 实用计算机相关日语词汇,计算机相关日语词汇整理2
  4. Go创建赋值channel
  5. HDLBits答案(18)_Verilog有限状态机(5)
  6. 立即学习AI:03-使用卷积神经网络进行马铃薯分类
  7. SpringBootAdmin安全配置
  8. python程序的name的作用是什么_python 中__name__ = '__main__' 的作用,到底干嘛的?
  9. c++对象回收问题_从垃圾回收解开Golang内存管理的面纱之三垃圾回收
  10. package.json的进阶
  11. 51nod 省选联测 R2
  12. 计算机考研 东华大学,东华大学(专业学位)计算机技术考研难吗
  13. html获取页面input值,javascript怎么获取input中用户输入的内容?
  14. 印象笔记如何分享链接_印象笔记共享问题解决经过
  15. 使用Python进行Android自动化测试
  16. 迅捷pdf转换器——如何提取pdf中的图片
  17. Gos —— shell程序
  18. OneZero第一次站立会议Sprint Planning Meeting(2016.3.21)
  19. 怎样进行微信营销才比较好
  20. tr闭包_蓝色的梦 的动态 - SegmentFault 思否

热门文章

  1. 请求列出指定服务器上的可用功能失败_滥用 ESI 详解(上)
  2. em算法示例_带有示例HTML'em'标签
  3. Java枚举getDeclaringClass()方法与示例
  4. Spring 事务失效的 8 大场景,面试官直呼666...
  5. JVM(六)为什么新生代有两个Survivor分区? 1
  6. Python获取电脑CPU序列号、主板序列号、BIOS序列号、硬盘序列号列表、网卡MAC地址
  7. 使用Bazel编译报错ERROR: Unrecognized option: --experimental_repo_remote_exec解决方法
  8. git 创建webpack项目_从0到1开发一个小程序cli脚手架(一)创建页面/组件模版篇...
  9. python selenium自动化面试_18年selenium3+python3+unittest自动化测试教程(上)
  10. Java并发编程实战_福州java编程实战培训班排名