4.5 SocketChannel
Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。
操作步骤:
- 打开 SocketChannel
- 读写数据
- 关闭 SocketChannel
1. 客户端
@Test
public void client() {
SocketChannel socketChannel = null;
try {
//1.获取通道
socketChannel =
SocketChannel.open(new InetSocketAddress(6666));
//2.切换非阻塞模式
socketChannel.configureBlocking(false);
//3.分配指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024);
//4.发送数据给服务器
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String str = scanner.next();
buf.put((new Date().toString() + "\n" + str).getBytes());
buf.flip();
socketChannel.write(buf);
buf.clear();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socketChannel != null) {
try {
socketChannel.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
}
4.6 ServerSocketChannel
Java NIO中的 ServerSocketChannel 是一个可以监听新进来的TCP连接的通道,就像标准IO中的ServerSocket一样
@Test
public void service() {
ServerSocketChannel socketChannel = null;
SocketChannel sc = null;
try {
//1.获取通道
socketChannel = ServerSocketChannel.open();
//2.切换非阻塞模式
socketChannel.configureBlocking(false);
//3.绑定连接
socketChannel.bind(new InetSocketAddress(6666));
//4. 获取选择器
Selector selector = Selector.open();
//5.将通道注册到选择器上, 并且指定"监听接受事件"
socketChannel.register(selector, SelectionKey.OP_ACCEPT);
//6.轮询式获取选择器上已经"准备就绪"的事件
while (selector.select() > 0) {
//7.获取当前选择器中所有注册的"选择键(已就绪的监听事件)"
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
//8. 获取准备"就绪"的是事件
SelectionKey sk = it.next();
//9. 判断具体是什么事件就绪
//接受事件是否就绪
if (sk.isAcceptable()) {
//10. 若"接受就绪", 获取客户端连接
sc = socketChannel.accept();
//11. 切换非阻塞模式
sc.configureBlocking(false);
//12. 将通道注册到选择器上
sc.register(selector, SelectionKey.OP_READ);
} else if (sk.isReadable()) {
//13. 获取当前选择器上"读就绪"状态的通道
sc = (SocketChannel) sk.channel();
//14.读取
ByteBuffer buf = ByteBuffer.allocate(1024);
int len = 0;
while ((len = sc.read(buf)) > 0) {
buf.flip();
System.out.println(new String(buf.array(), 0, len));
buf.clear();
}
}
}
it.remove();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socketChannel != null) {
try {
socketChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.7 DatagramChannel
Java NIO中的DatagramChannel是一个能收发UDP包的通道。
操作步骤:
- 打开 DatagramChannel
- 接收/发送数据
@Test
public void send() throws IOException{
DatagramChannel dc = DatagramChannel.open();
dc.configureBlocking(false);
ByteBuffer buf = ByteBuffer.allocate(1024);
Scanner scan = new Scanner(System.in);
while(scan.hasNext()){
String str = scan.next();
buf.put((new Date().toString() + ":\n" + str).getBytes());
buf.flip();
dc.send(buf, new InetSocketAddress("127.0.0.1", 9898));
buf.clear();
}
dc.close();
}
@Test
public void receive() throws IOException{
DatagramChannel dc = DatagramChannel.open();
dc.configureBlocking(false);
dc.bind(new InetSocketAddress(9898));
Selector selector = Selector.open();
dc.register(selector, SelectionKey.OP_READ);
while(selector.select() > 0){
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while(it.hasNext()){
SelectionKey sk = it.next();
if(sk.isReadable()){
ByteBuffer buf = ByteBuffer.allocate(1024);
dc.receive(buf);
buf.flip();
System.out.println(new String(buf.array(), 0, buf.limit()));
buf.clear();
}
}
it.remove();
}
}
网友评论