一、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/n/370521.html
微信扫一扫
支付宝扫一扫