一、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-hk/n/370521.html
微信掃一掃
支付寶掃一掃