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中文参考手册》,也希望大家多多支持毛票票。