一、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