一、SocketChannel和Socket的區別
Socket和SocketChannel都是Java提供的網絡編程接口,最大的區別在於Socket是基於流的,而SocketChannel是基於緩衝區的
Socket主要是提供了InputStream和OutputStream兩個流對象,當調用read方法時,程序會阻塞直到有數據讀取。而SocketChannel提供了一個Buffer對象,可以將從客戶端讀取的數據存放到Buffer中,這個過程是非阻塞的
SocketChannel還支持多路復用,一個線程可以同時處理多個客戶端連接請求,提高了程序的並發性能
import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; public class SocketChannelExample { public static void main(String[] args) throws Exception { SocketChannel channel = SocketChannel.open(); channel.connect(new InetSocketAddress("localhost", 9999)); String data = "Hello server"; ByteBuffer buf = ByteBuffer.allocate(48); buf.clear(); buf.put(data.getBytes()); buf.flip(); while(buf.hasRemaining()) { channel.write(buf); } channel.close(); } }
二、SocketChannel讀取數據
SocketChannel可以通過read方法讀取客戶端發送過來的數據,但是read方法是阻塞的,所以可以使用Selector來實現非阻塞讀取
import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Iterator; public class SocketChannelReadExample { public static void main(String[] args) throws Exception { Selector selector = Selector.open(); SocketChannel channel = SocketChannel.open(); channel.configureBlocking(false); channel.register(selector, SelectionKey.OP_CONNECT); channel.connect(new InetSocketAddress("localhost", 9999)); while (true) { int numKeys = selector.select(); if(numKeys == 0) { continue; } Iterator<SelectionKey> it = selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey key = it.next(); if(key.isConnectable()) { SocketChannel sc = (SocketChannel) key.channel(); while (sc.isConnectionPending()) { sc.finishConnect(); } sc.register(selector, SelectionKey.OP_READ); sc.write(ByteBuffer.wrap("Hello server".getBytes())); } else if(key.isReadable()) { SocketChannel sc = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); sc.read(buffer); buffer.flip(); System.out.println(new String(buffer.array())); sc.close(); } it.remove(); } } } }
三、SocketChannel線程安全
SocketChannel是線程安全的,可以被多個線程同時訪問,因為它是基於緩衝區的,不會出現多個線程同時操作同一個數據的問題
四、SocketChannel非阻塞
SocketChannel是非阻塞的,它可以在等待數據的同時處理其他任務,提高程序並發性能
五、SocketChannel.write
SocketChannel的write方法和OutputStream的write方法類似,可以將數據輸出到客戶端
六、SocketChannel selector選取
Selector可以幫助我們實現多路復用,在一個線程中同時處理多個客戶端連接請求,提高程序的並發性能
原創文章,作者:JKKXU,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/370521.html