天天看點

Java網絡程式設計之非阻塞I/O用戶端TCP執行個體

 非阻塞I/O可以減少伺服器無用的等待,進而高效的處理其他工作。能夠讓一個線程負責多個連接配接,而不是為每一個Socket都配置設定一個連接配接,在該線程中,選取負責多個連接配接中的一個已經準備好接收資料的連接配接,進而盡快的用資料進行填充,進而轉下下一個準備好的連接配接。

 傳統意義上的連接配接,會每次都會産生大量的線程,線程切換會耗費很大的時間。

 當然非阻塞I/O主要是未伺服器端設計的,不過這裡是主要模拟一下,論述用戶端利用通道和緩沖區的時候的流程。

 在這裡執行個體一個用戶端的基于通道和緩沖區的連接配接。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

<code>package</code> <code>com.nio.client;</code>

<code>import</code> <code>java.io.IOException;</code>

<code>import</code> <code>java.net.InetSocketAddress;</code>

<code>import</code> <code>java.net.SocketAddress;</code>

<code>import</code> <code>java.nio.ByteBuffer;</code>

<code>import</code> <code>java.nio.channels.Channels;</code>

<code>import</code> <code>java.nio.channels.SocketChannel;</code>

<code>import</code> <code>java.nio.channels.WritableByteChannel;</code>

<code>public</code> <code>class</code> <code>ChargenClient {</code>

<code>                                      </code> 

<code>    </code><code>private</code> <code>static</code> <code>final</code> <code>int</code> <code>DEFAULT_PORT=</code><code>19</code><code>;</code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>main(String[] args) {</code>

<code>        </code><code>// TODO Auto-generated method stub</code>

<code>        </code><code>try</code><code>{</code>

<code>            </code><code>SocketAddress address =</code><code>new</code> <code>InetSocketAddress(</code><code>"localhost"</code><code>,</code><code>2222</code><code>);</code>

<code>            </code><code>//利用給定的主機和端口建立一個通道,此時會自動連接配接,預設打開的通道是阻塞狀态道</code>

<code>            </code><code>//下一行代碼在建立連接配接之前不會被執行,失敗會抛出一個IOException</code>

<code>            </code><code>SocketChannel client=SocketChannel.open(address);</code>

<code>            </code><code>//設定該通道未非阻塞狀态</code>

<code>            </code><code>client.configureBlocking(</code><code>false</code><code>);</code>

<code>                                              </code> 

<code>            </code><code>//将讀取的資料直接寫入到通道中,不需要尋找該Socket的輸入流</code>

<code>            </code><code>//但是寫入與寫出的需要ByteBuffer 對象</code>

<code>            </code><code>ByteBuffer buffer=ByteBuffer.allocate(</code><code>80</code><code>);</code>

<code>            </code><code>//這裡先構造一個向System.out寫入位元組的通道</code>

<code>            </code><code>//但是它不對所得的信道進行緩沖,隻是将其 I/O 操作重定向到給定的流</code>

<code>            </code><code>WritableByteChannel out=Channels.newChannel(System.out);</code>

<code>            </code><code>//将此buffer對象傳遞給通道client的read方法,通道會将從</code>

<code>            </code><code>//socket讀取的資料自動的填充到該緩沖區buffer</code>

<code>            </code><code>//當緩沖區buffer有資料後,就會被複制到System.out</code>

<code>            </code><code>while</code><code>(client.read(buffer)!=-</code><code>1</code><code>)</code>

<code>            </code><code>{</code>

<code>                </code><code>//目的是從緩沖區的開頭讀取</code>

<code>                </code><code>buffer.flip();</code>

<code>                </code><code>out.write(buffer);</code>

<code>                </code><code>//這裡隻是将緩沖區重置到初始狀态,但是其緩沖區的資料依舊還在,</code>

<code>                </code><code>//隻不過會被新的資料馬上覆寫</code>

<code>                </code><code>buffer.clear();</code>

<code>            </code><code>}</code>

<code>            </code><code>//非阻塞下讀取資料方式,</code>

<code>            </code><code>//由于在非阻塞下,read會至少讀取一個位元組,當讀取不到資料的時候傳回0</code>

<code>            </code><code>while</code><code>(</code><code>true</code><code>)</code>

<code>                </code><code>int</code> <code>n=client.read(buffer);</code>

<code>                </code><code>if</code><code>(n&gt;</code><code>0</code><code>)</code>

<code>                </code><code>{</code>

<code>                    </code><code>buffer.flip();</code>

<code>                    </code><code>out.write(buffer);</code>

<code>                    </code><code>buffer.clear();</code>

<code>                </code><code>}</code>

<code>                </code><code>else</code> <code>if</code><code>( n==-</code><code>1</code><code>)</code>

<code>                    </code><code>break</code><code>;</code>

<code>        </code><code>}</code><code>catch</code><code>(IOException e)</code>

<code>        </code><code>{</code>

<code>            </code><code>System.out.println(e);</code>

<code>        </code><code>}</code>

<code>    </code><code>}</code>

<code>}</code>

本文轉自 zhao_xiao_long 51CTO部落格,原文連結:http://blog.51cto.com/computerdragon/1197500