java 阻塞 socket_java socket非阻塞I/O

1      非阻塞(Nonblocking)体系结构

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

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

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

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

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

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

2 SocketChannel 类

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

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

SocketChannel client = SocketChannel.open(rama) ;

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

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

b60c9848b8bdb26972b8b8877bdfc74a.png

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

送至服务器端。这看起来像是阻塞(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

4f1150b881333f12a311ae9ef34da474.pngpackagecn.bupt.channel;24f1150b881333f12a311ae9ef34da474.png34f1150b881333f12a311ae9ef34da474.pngimportjava.io.IOException;44f1150b881333f12a311ae9ef34da474.pngimportjava.net.InetSocketAddress;54f1150b881333f12a311ae9ef34da474.pngimportjava.net.SocketAddress;64f1150b881333f12a311ae9ef34da474.pngimportjava.nio.ByteBuffer;74f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.Channels;84f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.SocketChannel;94f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.WritableByteChannel;104f1150b881333f12a311ae9ef34da474.png114f1150b881333f12a311ae9ef34da474.pngimportcn.bupt.constant.Default;124f1150b881333f12a311ae9ef34da474.png131fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublicclassChargenClient9b8a8a44dd1c74ae49c20a7cd451974e.png{14d18c02628675d0a2c816449d98bda930.png15d18c02628675d0a2c816449d98bda930.pngpublicstaticintDEFAULT_PORT=8778;1697e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**17d18c02628675d0a2c816449d98bda930.png     *@paramargs18ecedf933ec37d714bd4c2545da43add2.png*/1997e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicstaticvoidmain(String[] args)9b8a8a44dd1c74ae49c20a7cd451974e.png{20d18c02628675d0a2c816449d98bda930.png//TODO Auto-generated method stub21d18c02628675d0a2c816449d98bda930.pngif(args.length==0)2297e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif9b8a8a44dd1c74ae49c20a7cd451974e.png{23d18c02628675d0a2c816449d98bda930.png           System.out.println("please input the port");24d18c02628675d0a2c816449d98bda930.pngreturn;25ecedf933ec37d714bd4c2545da43add2.png       }26d18c02628675d0a2c816449d98bda930.png27d18c02628675d0a2c816449d98bda930.pngintport ;28d18c02628675d0a2c816449d98bda930.png29d18c02628675d0a2c816449d98bda930.png30d18c02628675d0a2c816449d98bda930.png       port=DEFAULT_PORT ;31d18c02628675d0a2c816449d98bda930.png32d18c02628675d0a2c816449d98bda930.png       SocketAddress address=newInetSocketAddress(args[0] , port) ;3397e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry9b8a8a44dd1c74ae49c20a7cd451974e.png{34d18c02628675d0a2c816449d98bda930.png        SocketChannel client=SocketChannel.open(address) ;35d18c02628675d0a2c816449d98bda930.png        ByteBuffer buffer=ByteBuffer.allocate(74) ;36d18c02628675d0a2c816449d98bda930.png        WritableByteChannel out=Channels.newChannel(System.out) ;37d18c02628675d0a2c816449d98bda930.png38d18c02628675d0a2c816449d98bda930.pngwhile(client.read(buffer)!=-1)3997e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif9b8a8a44dd1c74ae49c20a7cd451974e.png{40d18c02628675d0a2c816449d98bda930.png            buffer.flip() ;41d18c02628675d0a2c816449d98bda930.png            out.write(buffer) ;42d18c02628675d0a2c816449d98bda930.png            buffer.clear() ;43d18c02628675d0a2c816449d98bda930.png44ecedf933ec37d714bd4c2545da43add2.png        }45d18c02628675d0a2c816449d98bda930.png46d18c02628675d0a2c816449d98bda930.png47d18c02628675d0a2c816449d98bda930.png48d18c02628675d0a2c816449d98bda930.png49d18c02628675d0a2c816449d98bda930.png50d18c02628675d0a2c816449d98bda930.png5197e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif    }catch(IOException e)9b8a8a44dd1c74ae49c20a7cd451974e.png{52d18c02628675d0a2c816449d98bda930.png//TODO Auto-generated catch block53d18c02628675d0a2c816449d98bda930.pnge.printStackTrace();54ecedf933ec37d714bd4c2545da43add2.png    }55d18c02628675d0a2c816449d98bda930.png56d18c02628675d0a2c816449d98bda930.png57d18c02628675d0a2c816449d98bda930.png58ecedf933ec37d714bd4c2545da43add2.png    }59d18c02628675d0a2c816449d98bda930.png608f1ba5b45633e9678d1db480c16cae3f.png}614f1150b881333f12a311ae9ef34da474.png

(2) 服务器端

1

4f1150b881333f12a311ae9ef34da474.pngpackagecn.bupt.channel;24f1150b881333f12a311ae9ef34da474.png34f1150b881333f12a311ae9ef34da474.pngimportjava.io.IOException;44f1150b881333f12a311ae9ef34da474.pngimportjava.net.InetSocketAddress;54f1150b881333f12a311ae9ef34da474.pngimportjava.net.ServerSocket;64f1150b881333f12a311ae9ef34da474.pngimportjava.nio.ByteBuffer;74f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.SelectionKey;84f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.Selector;94f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.ServerSocketChannel;104f1150b881333f12a311ae9ef34da474.pngimportjava.nio.channels.SocketChannel;114f1150b881333f12a311ae9ef34da474.pngimportjava.util.Iterator;124f1150b881333f12a311ae9ef34da474.pngimportjava.util.Set;134f1150b881333f12a311ae9ef34da474.png141fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublicclassChargenServer9b8a8a44dd1c74ae49c20a7cd451974e.png{15d18c02628675d0a2c816449d98bda930.png16d18c02628675d0a2c816449d98bda930.pngpublicstaticfinalintDEFAULT_PORT=8778;1797e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**18d18c02628675d0a2c816449d98bda930.png     *@paramargs19ecedf933ec37d714bd4c2545da43add2.png*/2097e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicstaticvoidmain(String[] args)9b8a8a44dd1c74ae49c20a7cd451974e.png{21d18c02628675d0a2c816449d98bda930.png//TODO Auto-generated method stub22d18c02628675d0a2c816449d98bda930.pngintport ;23d18c02628675d0a2c816449d98bda930.png        port=DEFAULT_PORT ;24d18c02628675d0a2c816449d98bda930.png25d18c02628675d0a2c816449d98bda930.pngbyte[] rotation=newbyte[95*2] ;26d18c02628675d0a2c816449d98bda930.pngfor(bytei=''; i

3c6cafce68eb941a00f1998f1d3d3aa6.gif9b8a8a44dd1c74ae49c20a7cd451974e.png{28d18c02628675d0a2c816449d98bda930.png            rotation[i-'']=i ;29d18c02628675d0a2c816449d98bda930.png            rotation[i+95-'']=i ;30ecedf933ec37d714bd4c2545da43add2.png        }31d18c02628675d0a2c816449d98bda930.png32d18c02628675d0a2c816449d98bda930.png        ServerSocketChannel serverChannel=null;33d18c02628675d0a2c816449d98bda930.png        Selector selector=null;34d18c02628675d0a2c816449d98bda930.png35d18c02628675d0a2c816449d98bda930.png3697e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**37d18c02628675d0a2c816449d98bda930.png         * 先建立服务器端的通道38d18c02628675d0a2c816449d98bda930.png         *39ecedf933ec37d714bd4c2545da43add2.png*/40d18c02628675d0a2c816449d98bda930.png4197e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry9b8a8a44dd1c74ae49c20a7cd451974e.png{42d18c02628675d0a2c816449d98bda930.png            serverChannel=ServerSocketChannel.open() ;43d18c02628675d0a2c816449d98bda930.png            ServerSocket ss=serverChannel.socket() ;44d18c02628675d0a2c816449d98bda930.png            InetSocketAddress address=newInetSocketAddress(port) ;45d18c02628675d0a2c816449d98bda930.png            ss.bind(address) ;46d18c02628675d0a2c816449d98bda930.png            serverChannel.configureBlocking(false) ;47d18c02628675d0a2c816449d98bda930.png            selector=Selector.open() ;48d18c02628675d0a2c816449d98bda930.png            serverChannel.register(selector, SelectionKey.OP_ACCEPT) ;49d18c02628675d0a2c816449d98bda930.png50d18c02628675d0a2c816449d98bda930.png51d18c02628675d0a2c816449d98bda930.png5297e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif        }catch(IOException e)9b8a8a44dd1c74ae49c20a7cd451974e.png{53d18c02628675d0a2c816449d98bda930.png//TODO Auto-generated catch block54d18c02628675d0a2c816449d98bda930.pnge.printStackTrace();55ecedf933ec37d714bd4c2545da43add2.png        }56d18c02628675d0a2c816449d98bda930.png57d18c02628675d0a2c816449d98bda930.png58d18c02628675d0a2c816449d98bda930.pngwhile(true)5997e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif9b8a8a44dd1c74ae49c20a7cd451974e.png{60d18c02628675d0a2c816449d98bda930.png6197e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry9b8a8a44dd1c74ae49c20a7cd451974e.png{62d18c02628675d0a2c816449d98bda930.png                selector.select() ;6397e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }catch(IOException e)9b8a8a44dd1c74ae49c20a7cd451974e.png{64d18c02628675d0a2c816449d98bda930.png                e.printStackTrace();65ecedf933ec37d714bd4c2545da43add2.png            }66d18c02628675d0a2c816449d98bda930.png67d18c02628675d0a2c816449d98bda930.png            Set readyKeys=selector.selectedKeys() ;68d18c02628675d0a2c816449d98bda930.png            Iterator iter=readyKeys.iterator() ;69d18c02628675d0a2c816449d98bda930.pngwhile(iter.hasNext())7097e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif9b8a8a44dd1c74ae49c20a7cd451974e.png{71d18c02628675d0a2c816449d98bda930.png                SelectionKey key=(SelectionKey) iter.next() ;72d18c02628675d0a2c816449d98bda930.png                iter.remove() ;73d18c02628675d0a2c816449d98bda930.png74d18c02628675d0a2c816449d98bda930.pngif(key.isAcceptable())7597e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif9b8a8a44dd1c74ae49c20a7cd451974e.png{76d18c02628675d0a2c816449d98bda930.png                    ServerSocketChannel server=(ServerSocketChannel) key.channel() ;7797e794c86028c5f5b5461ae5ef440a4c.png

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

3c6cafce68eb941a00f1998f1d3d3aa6.gif                    }catch(IOException e)9b8a8a44dd1c74ae49c20a7cd451974e.png{93d18c02628675d0a2c816449d98bda930.png//TODO Auto-generated catch block94d18c02628675d0a2c816449d98bda930.pnge.printStackTrace();95ecedf933ec37d714bd4c2545da43add2.png                    }96d18c02628675d0a2c816449d98bda930.png97d18c02628675d0a2c816449d98bda930.png98d18c02628675d0a2c816449d98bda930.png99d18c02628675d0a2c816449d98bda930.png100ecedf933ec37d714bd4c2545da43add2.png                }101d18c02628675d0a2c816449d98bda930.png102d18c02628675d0a2c816449d98bda930.pngelse103d18c02628675d0a2c816449d98bda930.pngif(key.isWritable())10497e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif9b8a8a44dd1c74ae49c20a7cd451974e.png{105d18c02628675d0a2c816449d98bda930.png10697e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**107d18c02628675d0a2c816449d98bda930.png                         * 建立客户端通道108d18c02628675d0a2c816449d98bda930.png                         *109ecedf933ec37d714bd4c2545da43add2.png*/110d18c02628675d0a2c816449d98bda930.png                        SocketChannel client=(SocketChannel)key.channel() ;111d18c02628675d0a2c816449d98bda930.png                        ByteBuffer buffer=(ByteBuffer) key.attachment() ;112d18c02628675d0a2c816449d98bda930.pngif(!buffer.hasRemaining())11397e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif9b8a8a44dd1c74ae49c20a7cd451974e.png{114d18c02628675d0a2c816449d98bda930.png                            buffer.rewind() ;115d18c02628675d0a2c816449d98bda930.pngintfirst=buffer.get() ;116d18c02628675d0a2c816449d98bda930.png                            buffer.rewind() ;117d18c02628675d0a2c816449d98bda930.pngintposition=first-''+1;118d18c02628675d0a2c816449d98bda930.png                            buffer.put(rotation , position ,72) ;119d18c02628675d0a2c816449d98bda930.png                            buffer.put((byte)'\r') ;120d18c02628675d0a2c816449d98bda930.png                            buffer.put((byte)'\n');121d18c02628675d0a2c816449d98bda930.png                            buffer.flip() ;122ecedf933ec37d714bd4c2545da43add2.png                        }12397e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry9b8a8a44dd1c74ae49c20a7cd451974e.png{124d18c02628675d0a2c816449d98bda930.png                            client.write(buffer) ;12597e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif                        }catch(IOException e)9b8a8a44dd1c74ae49c20a7cd451974e.png{126d18c02628675d0a2c816449d98bda930.png//TODO Auto-generated catch block127d18c02628675d0a2c816449d98bda930.pnge.printStackTrace();128ecedf933ec37d714bd4c2545da43add2.png                        }129ecedf933ec37d714bd4c2545da43add2.png                    }130d18c02628675d0a2c816449d98bda930.png131d18c02628675d0a2c816449d98bda930.png132d18c02628675d0a2c816449d98bda930.png133d18c02628675d0a2c816449d98bda930.png134d18c02628675d0a2c816449d98bda930.png135d18c02628675d0a2c816449d98bda930.png136d18c02628675d0a2c816449d98bda930.png137d18c02628675d0a2c816449d98bda930.png138d18c02628675d0a2c816449d98bda930.png                key.cancel() ;13997e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry9b8a8a44dd1c74ae49c20a7cd451974e.png{140d18c02628675d0a2c816449d98bda930.png                    key.channel().close() ;14197e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif                }catch(IOException e)9b8a8a44dd1c74ae49c20a7cd451974e.png{142d18c02628675d0a2c816449d98bda930.png//TODO Auto-generated catch block143d18c02628675d0a2c816449d98bda930.pnge.printStackTrace();144ecedf933ec37d714bd4c2545da43add2.png                }145ecedf933ec37d714bd4c2545da43add2.png            }146d18c02628675d0a2c816449d98bda930.png147d18c02628675d0a2c816449d98bda930.png148ecedf933ec37d714bd4c2545da43add2.png        }149d18c02628675d0a2c816449d98bda930.png150d18c02628675d0a2c816449d98bda930.png151d18c02628675d0a2c816449d98bda930.png152d18c02628675d0a2c816449d98bda930.png153d18c02628675d0a2c816449d98bda930.png154d18c02628675d0a2c816449d98bda930.png155d18c02628675d0a2c816449d98bda930.png156d18c02628675d0a2c816449d98bda930.png157d18c02628675d0a2c816449d98bda930.png158ecedf933ec37d714bd4c2545da43add2.png    }159d18c02628675d0a2c816449d98bda930.png1608f1ba5b45633e9678d1db480c16cae3f.png}1614f1150b881333f12a311ae9ef34da474.png

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值