标签:java serversocketchannel socketchannel
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);
例子如下:
服务端:
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();
}
}客户端如下:
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();
}
}启动方式:
先启动服务器端,然后再启动客户端
本文出自 “XEJ分布式工作室” 博客,请务必保留此出处http://xingej.blog.51cto.com/7912529/1968844
Java NIO 之 ServerSocketChannel 与 SocketChannel
标签:java serversocketchannel socketchannel
原文地址:http://xingej.blog.51cto.com/7912529/1968844