日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
在Java中使用NIO進(jìn)行網(wǎng)絡(luò)編程

在JDK中,有一個非常有意思的庫:NIO(New I/O)。這個庫中有3個重要的類,分別是java.nio.channels中Selector和Channel,以及java.nio中的Buffer。

創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),姑蘇企業(yè)網(wǎng)站建設(shè),姑蘇品牌網(wǎng)站建設(shè),網(wǎng)站定制,姑蘇網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,姑蘇網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

本篇文章我們首先了解一下為什么需要NIO來進(jìn)行網(wǎng)絡(luò)編程,然后看看一步一步來講解如何在網(wǎng)絡(luò)編程中使用NIO。

為什么需要NIO

使用Java編寫過Socket程序的同學(xué)一定都知道Socket和SocketServer。當(dāng)調(diào)用某個調(diào)用的時候,調(diào)用的地方就會阻塞,等待響應(yīng)。這種方式對于小規(guī)模的程序非常方便,但是對于大型的程序就有點(diǎn)力不從心了,當(dāng)有大量的連接的時候,我們可以為每一個連接建立一個線程來操作。但是這種做法帶來的缺陷也是顯而易見的:

  1. 硬件能夠支持大量的并發(fā)。
  2. 并發(fā)的數(shù)量始終有一個上限。
  3. 各個線程之間的優(yōu)先級不好控制。
  4. 各個Client之間的交互與同步困難。

我們也可以使用一個線程來處理所有的請求,使用不阻塞的IO,輪詢查詢所有的Client。這種做法同樣也有缺陷:無法迅速響應(yīng)Client端,同時會消耗大量輪詢查詢的時間。

所以,我們需要一種poll的模式來處理這種情況,從大量的網(wǎng)絡(luò)連接中找出來真正需要服務(wù)的Client。這正是NIO誕生的原因:提供一種Poll的模式,在所有的Client中找到需要服務(wù)的Client。

回到我們剛剛說到的3個最最重要的Class:java.nio.channels中Selector和Channel,以及java.nio中的Buffer。

Channel代表一個可以被用于Poll操作的對象(可以是文件流也可以使網(wǎng)絡(luò)流),Channel能夠被注冊到一個Selector中。通過調(diào)用Selector的select方法可以從所有的Channel中找到需要服務(wù)的實(shí)例(Accept,read ..)。

Buffer對象提供讀寫數(shù)據(jù)的緩存。相對于我們熟悉的Stream對象,Buffer提供更好的性能以及更好的編程透明性(人為控制緩存的大小以及具體的操作)。

配合BUFFER使用CHANNEL

與傳統(tǒng)模式的編程不用,Channel不使用Stream,而是Buffer。我們來實(shí)現(xiàn)一個簡單的非阻塞Echo Client:

 
 
 
  1. package com.cnblogs.gpcuster; 
  2.  
  3. import java.net.InetSocketAddress; 
  4. import java.net.SocketException; 
  5. import java.nio.ByteBuffer; 
  6. import java.nio.channels.SocketChannel; 
  7.  
  8. public class TCPEchoClientNonblocking { 
  9. public static void main(String args[]) throws Exception { 
  10. if ((args.length < 2) || (args.length > 3))// Testforcorrect#ofargs 
  11. throw new IllegalArgumentException( 
  12. "Parameter(s):   []"); 
  13. String server = args[0];// ServernameorIPaddress 
  14. // ConvertinputStringtobytesusingthedefaultcharset 
  15. byte[] argument = args[1].getBytes(); 
  16. int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7; 
  17. // Createchannelandsettononblocking 
  18. SocketChannel clntChan = SocketChannel.open(); 
  19. clntChan.configureBlocking(false); 
  20. // Initiateconnectiontoserverandrepeatedlypolluntilcomplete 
  21. if (!clntChan.connect(new InetSocketAddress(server, servPort))) { 
  22. while (!clntChan.finishConnect()) { 
  23. System.out.print(".");// Dosomethingelse 
  24. ByteBuffer writeBuf = ByteBuffer.wrap(argument); 
  25. ByteBuffer readBuf = ByteBuffer.allocate(argument.length); 
  26. int totalBytesRcvd = 0;// Totalbytesreceivedsofar 
  27. int bytesRcvd;// Bytesreceivedinlastread 
  28. while (totalBytesRcvd < argument.length) { 
  29. if (writeBuf.hasRemaining()) { 
  30. clntChan.write(writeBuf); 
  31. if ((bytesRcvd = clntChan.read(readBuf)) == -1) { 
  32. throw new SocketException("Connection closed prematurely"); 
  33. totalBytesRcvd += bytesRcvd; 
  34. System.out.print(".");// Dosomethingelse 
  35. System.out.println("Received:" + // converttoStringperdefaultcharset 
  36. new String(readBuf.array(), 0, totalBytesRcvd)); 
  37. clntChan.close(); 

這段代碼使用ByteBuffer來保存讀寫的數(shù)據(jù)。通過clntChan.configureBlocking(false); 設(shè)置后,其中的connect,read,write操作都不回阻塞,而是立刻放回結(jié)果。

使用SELECTOR

Selector的可以從所有的被注冊到自己Channel中找到需要服務(wù)的實(shí)例。

我們來實(shí)現(xiàn)Echo Server。

首先,定義一個接口:

 
 
 
  1. package com.cnblogs.gpcuster; 
  2.  
  3. import java.nio.channels.SelectionKey; 
  4. import java.io.IOException; 
  5.  
  6. public interface TCPProtocol { 
  7. void handleAccept(SelectionKey key) throws IOException; 
  8.  
  9. void handleRead(SelectionKey key) throws IOException; 
  10.  
  11. void handleWrite(SelectionKey key) throws IOException; 
  12. 我們的Echo Server將使用這個接口。然后我們實(shí)現(xiàn)Echo Server: 
  13. import java.io.IOException; 
  14. import java.net.InetSocketAddress; 
  15. import java.nio.channels.SelectionKey; 
  16. import java.nio.channels.Selector; 
  17. import java.nio.channels.ServerSocketChannel; 
  18. import java.util.Iterator; 
  19.  
  20. public class TCPServerSelector { 
  21. private static final int BUFSIZE = 256;// Buffersize(bytes) 
  22. private static final int TIMEOUT = 3000;// Waittimeout(milliseconds) 
  23.  
  24. public static void main(String[] args) throws IOException { 
  25. if (args.length < 1) {// Testforcorrect#ofargs 
  26. throw new IllegalArgumentException("Parameter(s):..."); 
  27. // Createaselectortomultiplexlisteningsocketsandconnections 
  28. Selector selector = Selector.open(); 
  29. // Createlisteningsocketchannelforeachportandregisterselector 
  30. for (String arg : args) { 
  31. ServerSocketChannel listnChannel = ServerSocketChannel.open(); 
  32. listnChannel.socket().bind( 
  33. new InetSocketAddress(Integer.parseInt(arg))); 
  34. listnChannel.configureBlocking(false);// mustbenonblockingtoregister 
  35. // Registerselectorwithchannel.Thereturnedkeyisignored 
  36. listnChannel.register(selector, SelectionKey.OP_ACCEPT); 
  37. // Createahandlerthatwillimplementtheprotocol 
  38. TCPProtocol protocol = new EchoSelectorProtocol(BUFSIZE); 
  39. while (true) {// Runforever,processingavailableI/Ooperations 
  40. // Waitforsomechanneltobeready(ortimeout) 
  41. if (selector.select(TIMEOUT) == 0) {// returns#ofreadychans 
  42. System.out.print("."); 
  43. continue; 
  44. // GetiteratoronsetofkeyswithI/Otoprocess 
  45. Iterator keyIter = selector.selectedKeys().iterator(); 
  46. while (keyIter.hasNext()) { 
  47. SelectionKey key = keyIter.next();// Keyisbitmask 
  48. // Serversocketchannelhaspendingconnectionrequests? 
  49. if (key.isAcceptable()) { 
  50. protocol.handleAccept(key); 
  51. // Clientsocketchannelhaspendingdata? 
  52. if (key.isReadable()) { 
  53. protocol.handleRead(key); 
  54. // Clientsocketchannelisavailableforwritingand 
  55. // keyisvalid(i.e.,channelnotclosed)? 
  56. if (key.isValid() && key.isWritable()) { 
  57. protocol.handleWrite(key); 
  58. keyIter.remove();// removefromsetofselectedkeys 

我們通過listnChannel.register(selector, SelectionKey.OP_ACCEPT); 注冊了一個我們感興趣的事件,然后調(diào)用selector.select(TIMEOUT)等待訂閱的時間發(fā)生,然后再采取相應(yīng)的處理措施。

***我們實(shí)現(xiàn)EchoSelectorProtocol

 
 
 
  1. package com.cnblogs.gpcuster; 
  2.  
  3. import java.nio.channels.SelectionKey; 
  4. import java.nio.channels.SocketChannel; 
  5. import java.nio.channels.ServerSocketChannel; 
  6. import java.nio.ByteBuffer; 
  7. import java.io.IOException; 
  8.  
  9. public class EchoSelectorProtocol implements TCPProtocol { 
  10. private int bufSize;// SizeofI/Obuffer 
  11.  
  12. public EchoSelectorProtocol(int bufSize) { 
  13. this.bufSize = bufSize; 
  14.  
  15. public void handleAccept(SelectionKey key) throws IOException { 
  16. SocketChannel clntChan = ((ServerSocketChannel) key.channel()).accept(); 
  17. clntChan.configureBlocking(false);// Mustbenonblockingtoregister 
  18. // Registertheselectorwithnewchannelforreadandattachbytebuffer 
  19. clntChan.register(key.selector(), SelectionKey.OP_READ, ByteBuffer 
  20. .allocate(bufSize)); 
  21.  
  22. public void handleRead(SelectionKey key) throws IOException { 
  23. // Clientsocketchannelhaspendingdata 
  24. SocketChannel clntChan = (SocketChannel) key.channel(); 
  25. ByteBuffer buf = (ByteBuffer) key.attachment(); 
  26. long bytesRead = clntChan.read(buf); 
  27. if (bytesRead == -1) {// Didtheotherendclose? 
  28. clntChan.close(); 
  29. } else if (bytesRead > 0) { 
  30. // Indicateviakeythatreading/writingarebothofinterestnow. 
  31. key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE); 
  32.  
  33. public void handleWrite(SelectionKey key) throws IOException { 
  34. /* 
  35. * Channelisavailableforwriting,andkeyisvalid(i.e.,clientchannel 
  36. * notclosed). 
  37. */ 
  38. // Retrievedatareadearlier 
  39. ByteBuffer buf = (ByteBuffer) key.attachment(); 
  40. buf.flip();// Preparebufferforwriting 
  41. SocketChannel clntChan = (SocketChannel) key.channel(); 
  42. clntChan.write(buf); 
  43. if (!buf.hasRemaining()) {// Buffercompletelywritten? 
  44. // Nothingleft,sonolongerinterestedinwrites 
  45. key.interestOps(SelectionKey.OP_READ); 
  46. buf.compact();// Makeroomformoredatatobereadin 

在這里,我們又進(jìn)一步對Selector注冊了相關(guān)的事件:key.interestOps(SelectionKey.OP_READ);

這樣,我們就實(shí)現(xiàn)了基于NIO的Echo 系統(tǒng)。


網(wǎng)站名稱:在Java中使用NIO進(jìn)行網(wǎng)絡(luò)編程
本文來源:http://m.5511xx.com/article/coepdsh.html