本文共 4416 字,大约阅读时间需要 14 分钟。
1、监听新进来的TCP链接通道,
2、创建新的SocketChannel
ServerSocketChannel并不能进行数据传输的能力
ServerSocketChannel socketChannel =ServerSocketChannel.open();
该对象关联了一个未绑定ServerSocket的通道,
JDK1.7前,需要调用ServerSocketChannel的socket方法,再调用bind()来进行关联
JDK1.7后,就可以直接调用ServerSocketChannel的bind()来进行端口绑定了。
通过 ServerSocketChannel.accept() 方法监听新进来的连接。
ServerSocketChannel 默认是 阻塞模式,可以查看JDK源码
如下,所示:
通过ServerSocketChannel.configureBlocking(true)来设定阻塞模式
1、在阻塞模式下,
如果有新的连接进来,那么accept()方法返回的是一个包含新进来的连接的SocketChannel,
如果没有新的连接,那么accept()方法,就会一直阻塞在这里,直到有的新连接进来
2、在非阻塞模式下ServerSocketChannel. configureBlocking(false)
如果有连接进来,那么accept()方法返回的是一个包含新进来的连接的SocketChannel
如果没有新的连接,那么accept()方法会立即返回null
3、阻塞模式与非阻塞模式的根本区别?
其实,就是在没有新的连接的情况下,如何处理的?不返回,一直等待的话,就是阻塞;
如果立即返回的话,就是非阻塞了。
方式一:在客户端创建
SocketChannel socketChannel = SocketChannel.open();
方式二:在服务器端创建
ServerSocketChannel接受一个连接请求后得到,如
SocketChannel socketChannel = serverSocketChannel.accept();
int read = socketChannel.read(sizeBuffer);
socketChannel.write(sizeBuffer);
例子如下:
服务端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | package xingej.channel; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; public class ServerSocketChannelTest { public void initChannel() throws IOException { //服务器端,通过open方法,来创建ServerSocketChannel //注意,此时,服务器端,还没有进行绑定端口呢 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); //设置为非阻塞模式 // serverSocketChannel.configureBlocking(false); //绑定端口号 //JDK1.7版本之后的写法 serverSocketChannel.bind( new InetSocketAddress( 8081 )); //JDK1.7版本之前的写法 // serverSocketChannel.socket().bind(new InetSocketAddress(8081)); //创建字节缓存区 //缓存区的大小是1024字节,这个可以自己调试,如改成64,128.... ByteBuffer byteBuffer = ByteBuffer.allocate( 1024 ); while ( true ) { System.out.println( "-------服务器端-----开始接收-----客户端的连接---------" ); //在服务器端,接收客户端的链接,如果存在客户端的话,就返回一个 //SocketChannel对象 //如果是阻塞模式的话,没有新的链接进来,就会阻塞在这里,否则,往下执行 //如果是非阻塞模式的话,没有新的链接进来,就会立马返回一个null,程序不会阻塞在这里, //会立马往下进行的 SocketChannel socketChannel = serverSocketChannel.accept(); if ( null != socketChannel) { while ( true ) { //清楚缓存区的数据,可以接收新的数据 byteBuffer.clear(); //将管道socketChannel的数据读取到 缓存byteBuffer里 //readSize 表示 读取的字节数 int readSize = socketChannel.read(byteBuffer); if (readSize == - 1 ) { break ; } //再从 字节缓存里,进行其他 业务逻辑操作,\ // 注意,这里的缓存区使用的字节类型 // 因此,如果需要其他类型的话,需要进行转换 System.out.println( new String(byteBuffer.array())); } } try { Thread.sleep( 1000 ); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws IOException { new ServerSocketChannelTest().initChannel(); } } |
客户端如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | package xingej.channel; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; public class SocketChannelTest { public void connectServer() throws IOException{ // 创建一个 SocketChannel对象, // 请注意,并没有进行 链接服务器端哦 SocketChannel socketChannel = SocketChannel.open(); //开始链接服务器端 socketChannel.connect( new InetSocketAddress( "localhost" , 8081 )); //在客户端创建 字节缓存区 ByteBuffer byteBuffer = ByteBuffer.allocate( 1024 ); String msg = "\nhello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream \n" + "hello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream \n" + "hello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream 北京\n" ; //往字节缓存区,添加数据 byteBuffer.put(msg.getBytes()); // 针对是更新limit值,将此值更新为position了,用于接下来的读操作 byteBuffer.flip(); while (byteBuffer.hasRemaining()) { //将字节缓存里的数据,写到管道中去 socketChannel.write(byteBuffer); } socketChannel.close(); } public static void main(String[] args) throws IOException{ new SocketChannelTest().connectServer(); } } |
启动方式:
先启动服务器端,然后再启动客户端
本文转自故新51CTO博客,原文链接:http://blog.51cto.com/xingej/1968844 ,如需转载请自行联系原作者