Java Socket编程实例(四)- NIO TCP实践
一、回传协议接口和TCP方式实现:
1.接口:
importjava.nio.channels.SelectionKey; importjava.io.IOException; publicinterfaceEchoProtocol{ voidhandleAccept(SelectionKeykey)throwsIOException; voidhandleRead(SelectionKeykey)throwsIOException; voidhandleWrite(SelectionKeykey)throwsIOException; }
2.实现:
importjava.nio.channels.*; importjava.nio.ByteBuffer; importjava.io.IOException; publicclassTCPEchoSelectorProtocolimplementsEchoProtocol{ privateintbufSize;//SizeofI/Obuffer publicEchoSelectorProtocol(intbufSize){ this.bufSize=bufSize; } publicvoidhandleAccept(SelectionKeykey)throwsIOException{ SocketChannelclntChan=((ServerSocketChannel)key.channel()).accept(); clntChan.configureBlocking(false);//Mustbenonblockingtoregister //Registertheselectorwithnewchannelforreadandattachbytebuffer clntChan.register(key.selector(),SelectionKey.OP_READ,ByteBuffer.allocate(bufSize)); } publicvoidhandleRead(SelectionKeykey)throwsIOException{ //Clientsocketchannelhaspendingdata SocketChannelclntChan=(SocketChannel)key.channel(); ByteBufferbuf=(ByteBuffer)key.attachment(); longbytesRead=clntChan.read(buf); if(bytesRead==-1){//Didtheotherendclose? clntChan.close(); }elseif(bytesRead>0){ //Indicateviakeythatreading/writingarebothofinterestnow. key.interestOps(SelectionKey.OP_READ|SelectionKey.OP_WRITE); } } publicvoidhandleWrite(SelectionKeykey)throwsIOException{ /* *Channelisavailableforwriting,andkeyisvalid(i.e.,clientchannel *notclosed). */ //Retrievedatareadearlier ByteBufferbuf=(ByteBuffer)key.attachment(); buf.flip();//Preparebufferforwriting SocketChannelclntChan=(SocketChannel)key.channel(); clntChan.write(buf); if(!buf.hasRemaining()){//Buffercompletelywritten? //Nothingleft,sonolongerinterestedinwrites key.interestOps(SelectionKey.OP_READ); } buf.compact();//Makeroomformoredatatobereadin } }
二、NIOTCP客户端:
importjava.net.InetSocketAddress; importjava.net.SocketException; importjava.nio.ByteBuffer; importjava.nio.channels.SocketChannel; publicclassTCPEchoClientNonblocking{ publicstaticvoidmain(Stringargs[])throwsException{ Stringserver="127.0.0.1";//ServernameorIPaddress //ConvertinputStringtobytesusingthedefaultcharset byte[]argument="0123456789abcdefghijklmnopqrstuvwxyz".getBytes(); intservPort=5500; //Createchannelandsettononblocking SocketChannelclntChan=SocketChannel.open(); clntChan.configureBlocking(false); //Initiateconnectiontoserverandrepeatedlypolluntilcomplete if(!clntChan.connect(newInetSocketAddress(server,servPort))){ while(!clntChan.finishConnect()){ System.out.print(".");//Dosomethingelse } } ByteBufferwriteBuf=ByteBuffer.wrap(argument); ByteBufferreadBuf=ByteBuffer.allocate(argument.length); inttotalBytesRcvd=0;//Totalbytesreceivedsofar intbytesRcvd;//Bytesreceivedinlastread while(totalBytesRcvd<argument.length){ if(writeBuf.hasRemaining()){ clntChan.write(writeBuf); } if((bytesRcvd=clntChan.read(readBuf))==-1){ thrownewSocketException("Connectionclosedprematurely"); } totalBytesRcvd+=bytesRcvd; System.out.print(".");//Dosomethingelse } System.out.println("Received:"+//converttoStringperdefaultcharset newString(readBuf.array(),0,totalBytesRcvd).length()); clntChan.close(); } }
三、NIOTCP服务端:
importjava.io.IOException; importjava.net.InetSocketAddress; importjava.nio.channels.*; importjava.util.Iterator; publicclassTCPServerSelector{ privatestaticfinalintBUFSIZE=256;//Buffersize(bytes) privatestaticfinalintTIMEOUT=3000;//Waittimeout(milliseconds) publicstaticvoidmain(String[]args)throwsIOException{ int[]ports={5500}; //Createaselectortomultiplexlisteningsocketsandconnections Selectorselector=Selector.open(); //Createlisteningsocketchannelforeachportandregisterselector for(intport:ports){ ServerSocketChannellistnChannel=ServerSocketChannel.open(); listnChannel.socket().bind(newInetSocketAddress(port)); listnChannel.configureBlocking(false);//mustbenonblockingtoregister //Registerselectorwithchannel.Thereturnedkeyisignored listnChannel.register(selector,SelectionKey.OP_ACCEPT); } //Createahandlerthatwillimplementtheprotocol TCPProtocolprotocol=newTCPEchoSelectorProtocol(BUFSIZE); while(true){//Runforever,processingavailableI/Ooperations //Waitforsomechanneltobeready(ortimeout) if(selector.select(TIMEOUT)==0){//returns#ofreadychans System.out.print("."); continue; } //GetiteratoronsetofkeyswithI/Otoprocess Iterator<SelectionKey>keyIter=selector.selectedKeys().iterator(); while(keyIter.hasNext()){ SelectionKeykey=keyIter.next();//Keyisbitmask //Serversocketchannelhaspendingconnectionrequests? if(key.isAcceptable()){ System.out.println("----accept-----"); protocol.handleAccept(key); } //Clientsocketchannelhaspendingdata? if(key.isReadable()){ System.out.println("----read-----"); protocol.handleRead(key); } //Clientsocketchannelisavailableforwritingand //keyisvalid(i.e.,channelnotclosed)? if(key.isValid()&&key.isWritable()){ System.out.println("----write-----"); protocol.handleWrite(key); } keyIter.remove();//removefromsetofselectedkeys } } } }
以上就是本文的全部内容,查看更多Java的语法,大家可以关注:《ThinkinginJava中文手册》、《JDK1.7参考手册官方英文版》、《JDK1.6APIjava中文参考手册》、《JDK1.5APIjava中文参考手册》,也希望大家多多支持毛票票。