日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

NIO:与 Buffer 一起使用 Channel

發(fā)布時(shí)間:2025/7/25 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NIO:与 Buffer 一起使用 Channel 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

如前文所述,Channel實(shí)例代表了一個(gè)與設(shè)備的連接,通過(guò)它可以進(jìn)行輸入輸出操作。實(shí)際上Channel的基本思想與我們見(jiàn)過(guò)的普通套接字非常相似。對(duì)于TCP協(xié)議,可以使用ServerSocketChannelSocketChannel。還有一些針對(duì)其他設(shè)備的其他類(lèi)型信道(如,FileChannel),盡管我們?cè)诤笪闹胁粫?huì)再提及,這里介紹的大部分內(nèi)容對(duì)于它們同樣適用。信道(channel)和套接字(socket)之間的不同點(diǎn)之一,可能是信道通常要調(diào)用靜態(tài)工廠方法來(lái)獲取實(shí)例:

SocketChannel clntChan = SocketChannel.open();

ServerSocketChannel servChan =

ServerSocketChannel.open();

?Channel使用的不是流,而是緩沖區(qū)來(lái)發(fā)送或讀取數(shù)據(jù)。Buffer類(lèi)或其任何子類(lèi)的實(shí)例都可以看作是一個(gè)定長(zhǎng)的Java基本數(shù)據(jù)類(lèi)型元素序列。與流不同,緩沖區(qū)有固定的、有限的容量,并由內(nèi)部(但可以被訪問(wèn))狀態(tài)記錄了有多少數(shù)據(jù)放入或取出,就像是有限容量的隊(duì)列一樣。Buffer是一個(gè)抽象類(lèi),只能通過(guò)創(chuàng)建它的子類(lèi)來(lái)獲得Buffer實(shí)例,而每個(gè)子類(lèi)都設(shè)計(jì)為用來(lái)容納一種Java基本數(shù)據(jù)類(lèi)型(boolean除外)。因此,這些實(shí)例分別為FloatBufferIntBuffer,或ByteBuffer,等等(ByteBuffer是這些實(shí)例中最靈活的,并將在后面很多例子中用到)。在channel中使用Buffer實(shí)例通常不是使用構(gòu)造函數(shù)創(chuàng)建的,而是通過(guò)調(diào)用allocate()方法創(chuàng)建指定容量的Buffer實(shí)例,

ByteBuffer buffer = ByteBuffer.allocate(CAPACITY);

或通過(guò)包裝一個(gè)已有的數(shù)組來(lái)創(chuàng)建:

ByteBuffer buffer = ByteBuffer.wrap(byteArray);?

?

NIO的強(qiáng)大功能部分來(lái)自于channel的非阻塞特性。回顧前面介紹的內(nèi)容可以知道,套接字的某些操作可能會(huì)無(wú)限期地阻塞。例如,對(duì)accept()方法的調(diào)用可能會(huì)因?yàn)榈却粋€(gè)客戶端連接而阻塞;對(duì)read()方法的調(diào)用可能會(huì)因?yàn)闆](méi)有數(shù)據(jù)可讀而阻塞,直到連接的另一端傳來(lái)新的數(shù)據(jù)??偟膩?lái)說(shuō),創(chuàng)建/接收連接或讀寫(xiě)數(shù)據(jù)等I/O調(diào)用,都可能無(wú)限期地阻塞等待,直到底層的網(wǎng)絡(luò)實(shí)現(xiàn)發(fā)生了什么。慢速的、有損耗的網(wǎng)絡(luò),或僅僅是簡(jiǎn)單的網(wǎng)絡(luò)故障都可能導(dǎo)致任意時(shí)間的延遲。然而不幸的是,在調(diào)用一個(gè)方法之前無(wú)法知道其是否會(huì)阻塞。NIOchannel抽象的一個(gè)重要特征就是可以通過(guò)配置它的阻塞行為,以實(shí)現(xiàn)非阻塞式的信道。

clntChan.configureBlocking(false);

?

在非阻塞式信道上調(diào)用一個(gè)方法總是會(huì)立即返回。這種調(diào)用的返回值指示了所請(qǐng)求的操作完成的程度。例如,在一個(gè)非阻塞式ServerSocketChannel上調(diào)用accept()方法,如果有連接請(qǐng)求在等待,則返回客戶端SocketChannel,否則返回null。下面我們來(lái)創(chuàng)建一個(gè)非阻塞TCP回顯客戶端??赡茏枞?/span>I/O操作包括建立連接,讀和寫(xiě)。通過(guò)使用非阻塞式信道,這些操作都將立即返回。我們必須反復(fù)調(diào)用這些操作,直到所有I/O操作都成功完成。

?

TCPEchoClientNonblocking.java

0 import java.net.InetSocketAddress;

1 import java.net.SocketException;

2 import java.nio.ByteBuffer;

3 import java.nio.channels.SocketChannel;

4

5 public class TCPEchoClientNonblocking {

6

7 public static void main(String args[]) throws Exception

{

8

9 if ((args.length < 2) || (args.length > 3)) // Test for

correct # of args

10 throw new IllegalArgumentException("Parameter(s):

<Server> <Word> [<Port>]");

11

12 String server = args[0]; // Server name or IP address

13 // Convert input String to bytes using the default

charset

14 byte[] argument = args[1].getBytes();

15

16 int servPort = (args.length == 3) ?

Integer.parseInt(args[2]) : 7;

17

18 // Create channel and set to nonblocking

19 SocketChannel clntChan = SocketChannel.open();

20 clntChan.configureBlocking(false);

21

22 // Initiate connection to server and repeatedly poll

until complete

23 if (!clntChan.connect(new InetSocketAddress(server,

servPort))) {

24 while (!clntChan.finishConnect()) {

25 System.out.print("."); // Do something else

26 }

27 }

28 ByteBuffer writeBuf = ByteBuffer.wrap(argument);

29 ByteBuffer readBuf =

ByteBuffer.allocate(argument.length);

30 int totalBytesRcvd = 0; // Total bytes received so far

31 int bytesRcvd; // Bytes received in last read

32 while (totalBytesRcvd < argument.length) {

33 if (writeBuf.hasRemaining()) {

34 clntChan.write(writeBuf);

35 }

36 if ((bytesRcvd = clntChan.read(readBuf)) == -1) {

37 throw new SocketException("Connection closed

prematurely");

38 }

39 totalBytesRcvd += bytesRcvd;

40 System.out.print("."); // Do something else

41 }

42

43 System.out.println("Received: " + // convert to String

per default charset

44 new String(readBuf.array(), 0, totalBytesRcvd));

45 clntChan.close();

46 }

47 }

?

TCPEchoClientNonblocking.java

?1.獲取并轉(zhuǎn)換參數(shù):第9-16

2.?創(chuàng)建非阻塞式SocketChannel:第19-20

3.連接服務(wù)器:第23-27?

由于該套接字是非阻塞式的,因此對(duì)connect()方法的調(diào)用可能會(huì)在連接建立之前返回,如果在返回前已經(jīng)成功建立了連接,則返回true,否則返回false。對(duì)于后一種情況,任何試圖發(fā)送或接收數(shù)據(jù)的操作都將拋出NotYetConnectedException異常,因此,我們通過(guò)持續(xù)調(diào)finishConnect()方法來(lái)"輪詢"連接狀態(tài),該方法在連接成功建立之前一直返回false。打印操作演示了在等待連接建立的過(guò)程中,程序還可以執(zhí)行其他任務(wù)。不過(guò),這種忙等的方法非常浪費(fèi)系統(tǒng)資源,這里這樣做只是為了演示該方法的使用。?

4.創(chuàng)建讀寫(xiě)緩沖區(qū):第28-29

?我們分別使用了兩種方法來(lái)創(chuàng)建將要用來(lái)讀寫(xiě)數(shù)據(jù)的ByteBuffer實(shí)例。一是通過(guò)包裝包含了要發(fā)送數(shù)據(jù)的byte[]數(shù)組,另一個(gè)方法是調(diào)用allocate()方法,創(chuàng)建具有與前面byte[]數(shù)組大小相同緩沖區(qū)的ByteBuffer實(shí)例。

?5.反復(fù)循環(huán)直到發(fā)送和接收完所有字節(jié):第32-41

只要輸出緩沖區(qū)中還留有數(shù)據(jù),就調(diào)用write()方法。對(duì)read()方法的調(diào)用不會(huì)阻塞等待,但是當(dāng)沒(méi)有數(shù)據(jù)可讀時(shí)該方法將返回0。這里,打印語(yǔ)句再次舉例說(shuō)明了在等待通信完成的過(guò)程中,程序可以執(zhí)行其他任務(wù)。

6.打印接收到的數(shù)據(jù):第43-44

7.關(guān)閉信道:第45

與套接字類(lèi)似,信道在完成其任務(wù)后也需要關(guān)閉。

?

相關(guān)下載:

Java_TCPIP_Socket編程(doc)

http://download.csdn.net/detail/undoner/4940239

?

文獻(xiàn)來(lái)源:

UNDONER(小杰博客) :http://blog.csdn.net/undoner

LSOFT.CN(瑯軟中國(guó)) :http://www.lsoft.cn

?

轉(zhuǎn)載于:https://www.cnblogs.com/wuyida/archive/2012/12/29/6301059.html

總結(jié)

以上是生活随笔為你收集整理的NIO:与 Buffer 一起使用 Channel的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。