JAVA-NIO之Socket/ServerSocket Channel(詳解)
一、ServerSocketChannel
Java NIO中的 ServerSocketChannel 是一個可以監(jiān)聽新進來的TCP連接的通道, 就像標準IO中的ServerSocket一樣。ServerSocketChannel類在 java.nio.channels包中。
打開 ServerSocketChannel
通過調(diào)用 ServerSocketChannel.open() 方法來打開ServerSocketChannel.
關(guān)閉 ServerSocketChannel
通過調(diào)用ServerSocketChannel.close() 方法來關(guān)閉ServerSocketChannel.
監(jiān)聽新進來的連接
通過 ServerSocketChannel.accept() 方法監(jiān)聽新進來的連接。當 accept()方法返回的時候,它返回一個包含新進來的連接的 SocketChannel。因此, accept()方法會一直阻塞到有新連接到達。
通常不會僅僅只監(jiān)聽一個連接,在while循環(huán)中調(diào)用 accept()方法.
當然,也可以在while循環(huán)中使用除了true以外的其它退出準則。
非阻塞模式
ServerSocketChannel可以設(shè)置成非阻塞模式。在非阻塞模式下,accept() 方法會立刻返回,如果還沒有新進來的連接,返回的將是null。 因此,需要檢查返回的SocketChannel是否是null.如:
/**
* socket server channel
*/
@Test
public void text2() throws IOException {
ServerSocketChannel channel = ServerSocketChannel.open(); //新建channel
channel.socket().bind(new InetSocketAddress(9999)); //監(jiān)聽端口
channel.configureBlocking(true); //設(shè)置阻塞
while (true) {
SocketChannel accept = channel.accept(); //設(shè)置為阻塞,則此方法阻塞,直到有連接
//如果設(shè)置為非阻塞,需要在這里判斷 accept == null?
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
accept.read(byteBuffer);
byteBuffer.flip(); //反轉(zhuǎn)
while (byteBuffer.hasRemaining()) { //判斷
System.err.println((char)byteBuffer.get()); //輸出
}
}
}
二、SocketChannel
Java NIO中的SocketChannel是一個連接到TCP網(wǎng)絡(luò)套接字的通道。可以通過以下2種方式創(chuàng)建SocketChannel:
打開一個SocketChannel并連接到互聯(lián)網(wǎng)上的某臺服務(wù)器。
一個新連接到達ServerSocketChannel時,會創(chuàng)建一個SocketChannel。
打開 SocketChannel
下面是SocketChannel的打開方式:
關(guān)閉 SocketChannel
當用完SocketChannel之后調(diào)用SocketChannel.close()關(guān)閉SocketChannel:
從 SocketChannel 讀取數(shù)據(jù)
要從SocketChannel中讀取數(shù)據(jù),調(diào)用一個read()的方法之一。
首先,分配一個Buffer。從SocketChannel讀取到的數(shù)據(jù)將會放到這個Buffer中。
然后,調(diào)用SocketChannel.read()。該方法將數(shù)據(jù)從SocketChannel 讀到Buffer中。read()方法返回的int值表示讀了多少字節(jié)進Buffer里。如果返回的是-1,表示已經(jīng)讀到了流的末尾(連接關(guān)閉了)。
寫入 SocketChannel
寫數(shù)據(jù)到SocketChannel用的是SocketChannel.write()方法,該方法以一個Buffer作為參數(shù)。
注意SocketChannel.write()方法的調(diào)用是在一個while循環(huán)中的。Write()方法無法保證能寫多少字節(jié)到SocketChannel。所以,我們重復(fù)調(diào)用write()直到Buffer沒有要寫的字節(jié)為止。
非阻塞模式
可以設(shè)置 SocketChannel 為非阻塞模式(non-blocking mode).設(shè)置之后,就可以在異步模式下調(diào)用connect(), read() 和write()了。
connect()
如果SocketChannel在非阻塞模式下,此時調(diào)用connect(),該方法可能在連接建立之前就返回了。為了確定連接是否建立,可以調(diào)用finishConnect()的方法。
write()
非阻塞模式下,write()方法在尚未寫出任何內(nèi)容時可能就返回了。所以需要在循環(huán)中調(diào)用write()。前面已經(jīng)有例子了,這里就不贅述了。
read()
非阻塞模式下,read()方法在尚未讀取到任何數(shù)據(jù)時可能就返回了。所以需要關(guān)注它的int返回值,它會告訴你讀取了多少字節(jié)。
非阻塞模式與選擇器
非阻塞模式與選擇器搭配會工作的更好,通過將一或多個SocketChannel注冊到Selector,可以詢問選擇器哪個通道已經(jīng)準備好了讀取,寫入等。Selector與SocketChannel的搭配使用會在后面詳講。
/**
* socket channel
*/
@Test
public void test3() throws IOException {
SocketChannel channel = SocketChannel.open(); //新建服務(wù)端
channel.connect(new InetSocketAddress("127.0.0.1",9999)); //連接服務(wù)端地址
ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //緩沖區(qū)
byteBuffer.put("123".getBytes());
byteBuffer.flip(); //反轉(zhuǎn)
while (byteBuffer.hasRemaining()) { //判斷
channel.write(byteBuffer);
}
}
以上這篇JAVA-NIO之Socket/ServerSocket Channel(詳解)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
解讀@Scheduled任務(wù)調(diào)度/定時任務(wù)非分布式
這篇文章主要介紹了解讀@Scheduled任務(wù)調(diào)度/定時任務(wù)非分布式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
Springboot2 session設(shè)置超時時間無效的解決
這篇文章主要介紹了Springboot2 session設(shè)置超時時間無效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
關(guān)于MyBatis 查詢數(shù)據(jù)時屬性中多對一的問題(多條數(shù)據(jù)對應(yīng)一條數(shù)據(jù))
這篇文章主要介紹了MyBatis 查詢數(shù)據(jù)時屬性中多對一的問題(多條數(shù)據(jù)對應(yīng)一條數(shù)據(jù)),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
Java并發(fā)編程ArrayBlockingQueue的使用
ArrayBlockingQueue是一個備受矚目的有界阻塞隊列,本文將全面深入地介紹ArrayBlockingQueue的內(nèi)部機制、使用場景以及最佳實踐,感興趣的可以了解一下2024-08-08

