成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java NIO TCP編程

開發(fā) 后端
在Java1.4以前,Java的網(wǎng)絡編程是只有阻塞方式的,在Java1.4以及之后,Java提供了非阻塞的網(wǎng)絡編程API.從Java的發(fā)展來看,由于Java的快速發(fā)展,JVM性能的提升,涉足到服務端應用程序開發(fā)也越來越多,要求高性能的網(wǎng)絡應用越來越多,這是Java推出非阻塞網(wǎng)絡編程的最主要原因吧。

在Java1.4以前,Java的網(wǎng)絡編程是只有阻塞方式的,在Java1.4以及之后,Java提供了非阻塞的網(wǎng)絡編程API.從Java的發(fā)展來看,由于Java的快速發(fā)展,JVM性能的提升,涉足到服務端應用程序開發(fā)也越來越多,要求高性能的網(wǎng)絡應用越來越多,這是Java推出非阻塞網(wǎng)絡編程的最主要原因吧。

對我而言,以前的大部分服務端應用主要是搭建在應用服務器之上,所以通訊這部分工作都是有應用服務器來實現(xiàn)和管理的。這次由于通訊和協(xié)議,我們必須自己實現(xiàn)一個能處理大量并發(fā)客戶端的高性能并行處理的Java服務端程序。因此,選擇非阻塞的處理方式也是必然的。我們首先來看看阻塞的處理方式:

在阻塞的網(wǎng)絡編程方式中,針對于每一個單獨的網(wǎng)絡連接,都必須有一個線程對應的綁定該網(wǎng)絡連接,進行網(wǎng)絡字節(jié)流的處理。下面是一段代碼:

  1. public static void main(String[] args) {  
  2. try {  
  3. ServerSocket ssc = new ServerSocket(23456);  
  4. while (true) {  
  5. System.out.println("Enter Accept:");  
  6. Socket s = ssc.accept();  
  7. try {  
  8. (new Thread(new Worker(s))).start();  
  9. catch (Exception e) {  
  10. // TODO  
  11. e.printStackTrace();  
  12. }  
  13. }  
  14. catch (IOException e) {  
  15. e.printStackTrace();  
  16. }   
  17.  
  18. }   
  19.  
  20. public static class Worker implements Runnable {  
  21. private Socket s;   
  22.  
  23. private boolean running = true;;   
  24.  
  25. public Worker(Socket s) {  
  26. this.s = s;  
  27. }   
  28.  
  29. public void run() {  
  30. try {  
  31. InputStream is = s.getInputStream();  
  32. OutputStream os = s.getOutputStream();  
  33. while (running) {  
  34. byte[] b = this.readByLength(is, 1024);  
  35. this.process(b);  
  36. }  
  37. catch (Throwable t) {  
  38. // TODO  
  39. t.printStackTrace();  
  40. }  
  41. }   
  42.  
  43. private byte[] readByLength(InputStream is, int contLen) throws IOException {  
  44. byte[] b = new byte[contLen];  
  45. int off = 0;  
  46. int length = 0;  
  47. while ((length = is.read(b, off, contLen - off)) >= 0) {  
  48. off = +length;  
  49. if (off >= contLen) {  
  50. break;  
  51. }  
  52. }  
  53. return b;  
  54. }   
  55.  
  56. private void process(byte[] b) {   
  57.  
  58. }  

 

在這段代碼中,我們看到有兩個阻塞的方法,是ServerSocket的accept()方法;和InputStream的read()方式。因此我們需要兩類型的線程分別進行處理。而且每一個阻塞方法所綁定的線程的生命周期和網(wǎng)絡連接的生命周期是一致的。基于以上的原因,NIO應運而生,一方面,為每一個網(wǎng)絡連接建立一個線程對應,同時每一個線程有大量的線程處于讀寫以外的空閑狀態(tài),因此希望降低線程的數(shù)量,降低每個空閑狀態(tài),提高單個線程的運行執(zhí)行效率,實際上是在更加充分運用CPU的計算、運行能力(因為,如果有大量的鏈路存在,就存在大量的線程,而大量的線程都阻塞在read()或者write()方法,同時CPU又需要來回頻繁的在這些線程中間調度和切換,必然帶來大量的系統(tǒng)調用和資源競爭.);另外一方面希望提高網(wǎng)絡IO和硬盤IO操作的性能。在NIO主要出現(xiàn)了三個新特性:

1.數(shù)據(jù)緩沖處理(ByteBuffer):由于操作系統(tǒng)和應用程序數(shù)據(jù)通信的原始類型是byte,也是IO數(shù)據(jù)操作的基本單元,在NIO中,每一個基本的原生類型(boolean除外)都有Buffer的實現(xiàn):CharBuffer、IntBuffer、DoubleBuffer、ShortBuffer、LongBuffer、FloatBuffer和ByteBuffer,數(shù)據(jù)緩沖使得在IO操作中能夠連續(xù)的處理數(shù)據(jù)流。當前有兩種ByteBuffer,一種是Direct ByteBuffer,另外一種是NonDirect ByteBuffer;ByteBuffer是普通的Java對象,遵循Java堆中對象存在的規(guī)則;而Direct ByteBuffer是native代碼,它內存的分配不在Java的堆棧中,不受Java內存回收的影響,每一個Direct ByteBuffer都是直接分配的一塊連續(xù)的內存空間,也是NIO提高性能的重要辦法之一。另外數(shù)據(jù)緩沖有一個很重要的特點是,基于一個數(shù)據(jù)緩沖可以建立一個或者多個邏輯的視圖緩沖(View Buffer).比方說,通過View Buffer,可以將一個Byte類型的Buffer換作Int類型的緩沖;或者一個大的緩沖轉作很多小的Buffer。之所以稱為View Buffer是因為這個轉換僅僅是邏輯上,在物理上并沒有創(chuàng)建新的Buffer。這為我們操作Buffer帶來諸多方便。

2.異步通道(Channel):Channel是一個與操作系統(tǒng)緊密結合的本地代碼較多的對象。通過Channel來實現(xiàn)網(wǎng)絡編程的非阻塞操作,同時也是其與ByteBuffer、Socket有效結合充分利用非阻塞、ByteBuffer的特性的。在后面我們會看到具體的SocketChannel的用法。

3.有條件的選擇(Readiness Selection):大多數(shù)操作系統(tǒng)都有支持有條件選擇準備就緒IO通道的API,即能夠保證一個線程同時有效管理多個IO通道。在NIO中,由Selector(維護注冊進來的Channel和這些Channel的狀態(tài))、SelectableChannel(能被Selector管理的Channel)和SelectionKey(SelectionKey標識Selector和SelectableChannel之間的映射關系,一旦一個Channel注冊到Selector中,就會返回一個SelectionKey對象。SelectionKey保存了兩類狀態(tài):對應的Channel注冊了哪些操作;對應的Channel的那些操作已經(jīng)準備好了,可以進行相應的數(shù)據(jù)操作了)結合來實現(xiàn)這個功能的。

 

NIO的包中主要包含了這樣幾種抽象數(shù)據(jù)類型:

◆  Buffer:包含數(shù)據(jù)且用于讀寫的線形表結構。其中還提供了一個特殊類用于內存映射文件的I/O操作。

◆ Charset:它提供Unicode字符串影射到字節(jié)序列以及逆映射的操作。

◆ Channels:包含socket,file和pipe三種管道,都是全雙工的通道。

◆ Selector:多個異步I/O操作集中到一個或多個線程中(可以被看成是Unix中select()函數(shù)的面向對象版本)。

NIO非阻塞的典型編程模型如下:

  1. private Selector selector = null;  
  2. private static final int BUF_LENGTH = 1024;  
  3. public void start() throws IOException {  
  4. if (selector != null) {  
  5. selector = Selector.open();  
  6. }  
  7. ServerSocketChannel ssc = ServerSocketChannel.open();  
  8. ServerSocket serverSocket = ssc.socket();  
  9. serverSocket.bind(new InetSocketAddress(80));  
  10. ssc.configureBlocking(false);  
  11. ssc.register(selector, SelectionKey.OP_ACCEPT);  
  12. try {  
  13. while (true) {  
  14. int nKeys = UnblockServer.this.selector.select();  
  15. if (nKeys > 0) {  
  16. Iterator it = selector.selectedKeys().iterator();  
  17. while (it.hasNext()) {  
  18. SelectionKey key = (SelectionKey) it.next();  
  19. if (key.isAcceptable()) {  
  20. ServerSocketChannel server = (ServerSocketChannel) key.channel();  
  21. SocketChannel channel = server.accept();  
  22. if (channel == null) {  
  23. continue;  
  24. }  
  25. channel.configureBlocking(false);  
  26. channel.register(selector, SelectionKey.OP_READ);  
  27. }  
  28. if (key.isReadable()) {  
  29. readDataFromSocket(key);  
  30. }  
  31. it.remove();  
  32. }  
  33. }  
  34. }  
  35. catch (IOException ioe) {  
  36. ioe.printStackTrace();  
  37. }  
  38. }  
  39. /**  
  40. * @param key  
  41. * @throws IOException  
  42. */ 
  43. private void readDataFromSocket(SelectionKey key) throws IOException {  
  44. ByteBuffer buf = ByteBuffer.allocate(BUF_LENGTH);  
  45. SocketChannel sc = (SocketChannel) key.channel();  
  46. int readBytes = 0;  
  47. int ret;  
  48. try {  
  49. while ((ret = sc.read(buf.buf())) > 0) {  
  50. readBytes += ret;  
  51. }  
  52. finally {  
  53. buf.flip();  
  54. }  
  55. // process buffer  
  56. // buf.clear();  

從這段程序,我們基本可以了解到NIO網(wǎng)絡編程的一些特點,創(chuàng)建一個SocketServer的方式已經(jīng)發(fā)生了變化,需要指定非阻塞模式,需要創(chuàng)建一個Channel然后注冊到Selector中去,同樣,建立一個網(wǎng)絡連接過程也是一樣的模式,然后就是有條件的選擇(Readiness Selection).這樣,我們的每一個線程只需要處理一類型的網(wǎng)絡選擇。在代碼上,我們發(fā)現(xiàn)處理的方式和阻塞完全不一樣了,我們需要完全重新考慮如何編寫網(wǎng)絡通信的模塊了:

1.持久連接的超時問題(Timeout),因為API沒有直接的支持timeout的參數(shù)設置功能,因此需要我們自己實現(xiàn)一個這樣功能。

2.如何使用Selector,由于每一個Selector的處理能力是有限的,因此在大量鏈接和消息處理過程中,需要考慮如何使用多個Selector.

3.在非阻塞情況下,read和write都不在是阻塞的,因此需要考慮如何完整的讀取到確定的消息;如何在確保在網(wǎng)絡環(huán)境不是很好的情況下,一定將數(shù)據(jù)寫進IO中。

4.如何應用ByteBuffer,本身大量創(chuàng)建ByteBuffer就是很耗資源的;如何有效的使用ByteBuffer?同時ByteBuffer的操作需要仔細考慮,因為有position()、mark()、limit()、capacity等方法。

5.由于每一個線程在處理網(wǎng)絡連接的時候,面對的都是一系列的網(wǎng)絡連接,需要考慮如何更好的使用、調度多線程。在對消息的處理上,也需要保證一定的順序,比方說,登錄消息***到達,只有登錄消息處理之后,才有可能去處理同一個鏈路上的其他類型的消息。

6.在網(wǎng)絡編程中可能出現(xiàn)的內存泄漏問題。

在NIO的接入處理框架上,大約有兩種并發(fā)線程:

1.Selector線程,每一個Selector單獨占用一個線程,由于每一個Selector的處理能力是有限的,因此需要多個Selector并行工作。

2.對于每一條處于Ready狀態(tài)的鏈路,需要線程對于相應的消息進行處理;對于這一類型的消息,需要并發(fā)線程共同工作進行處理。在這個過程中,不斷可能需要消息的完整性;還要涉及到,每個鏈路上的消息可能有時序,因此在處理上,也可能要求相應的時序性。

當前社區(qū)的開源NIO框架實現(xiàn)有MINA、Grizzly、NIO framework、QuickServer、xSocket等,其中MINA和Grizzly最為活躍,而且代碼的質量也很高。他們倆在實現(xiàn)的方法上也完全大不一樣。(大部分Java的開源服務器都已經(jīng)用NIO重寫了網(wǎng)絡部分。 )

不管是我們自己實現(xiàn)NIO的網(wǎng)絡編程框架,還是基于MINA、Grizzly等這樣的開源框架進行開發(fā),都需要理解確定的了解NIO帶來的益處和NIO編程需要解決的眾多類型的問題。充足、有效的單元測試,是我們寫好NIO代碼的好助手:)

 原文鏈接:http://www.cnblogs.com/zhuowei/archive/2009/03/19/1416421.html

責任編輯:林師授 來源: 卓韋的博客
相關推薦

2011-12-07 16:50:29

JavaNIO

2011-12-08 10:24:53

JavaNIO

2012-03-19 11:41:30

JavaSocket

2022-02-14 15:07:48

進程FileChanne線程

2019-09-05 14:21:22

JavaNIOBIO

2022-12-08 09:10:11

I/O模型Java

2024-08-08 15:46:34

2015-04-24 09:48:59

TCPsocketsocket編程

2012-09-24 15:13:50

C#網(wǎng)絡協(xié)議TCP

2023-03-31 07:49:51

syscall庫Echo Serve

2011-12-07 14:57:44

JavaNIO

2011-12-15 09:55:47

javanio

2011-12-15 11:19:08

JavaNIO

2019-09-18 20:07:06

AndroidTCP協(xié)議

2014-12-11 09:20:30

TCP

2021-06-11 17:26:06

代碼Java網(wǎng)絡編程

2012-01-06 13:58:47

JavaTCP

2011-12-15 10:10:33

Javanio

2011-12-15 10:43:20

JavaNIO

2022-02-22 08:00:48

JavaNIOBuffer
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美日韩精品久久久免费观看 | 久久一区二区免费视频 | 国产激情视频在线观看 | 欧美精品久久一区 | 在线视频 欧美日韩 | 人人澡视频| 国产成视频在线观看 | 国产精品精品视频 | 精品久久久久久久久久久 | 久久在线 | 久久精品一二三影院 | 欧美日一区二区 | 蜜桃视频成人 | 偷拍亚洲色图 | 国产精品99久 | 国产美女福利在线观看 | 精品国产欧美在线 | 黄色在线观看网站 | 亚洲免费观看视频网站 | 精品1区2区| 国产在线精品一区二区三区 | 天天干免费视频 | 精品国产乱码久久久久久丨区2区 | 欧美日一区二区 | 99热都是精品 | www.日韩欧美 | 欧美亚州 | 亚洲一区二区久久久 | 成人高清视频在线观看 | 精品91| 成人精品一区二区三区中文字幕 | 欧美电影免费观看 | 日韩一区二区视频 | 亚洲欧美成人影院 | 欧美成人一区二区三区 | 国产一区| 国产欧美一区二区三区另类精品 | 伊人伊成久久人综合网站 | 黄色三级毛片 | 日本特黄特色aaa大片免费 | 日韩美女在线看免费观看 |