服务端
package com.xbb.demo.twoway;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
/**
* 服务端
*/
public class NonServerSocket {
public static void main(String[] args) {
try(
ServerSocketChannel socketChannel = ServerSocketChannel.open().bind(new InetSocketAddress(9999));
){
String receMsg = "";
// 切换成非阻塞模式
socketChannel.configureBlocking(false);
// 获取一个选择器
Selector selector = Selector.open();
/**
* 把选择器注册到通道上并监听接收
* 参数一 : 所以注册的选择器
* 参数二 : SelectionKey
* 表示 SelectableChannel与Selector之前的关系,每次注册的时候需要选择一个事件.
* 有四种状态:
* SelectionKey.OP_ACCEPT : 接收
* SelectionKey.OP_CONNECT : 连接
* SelectionKey.OP_READ : 读
* SelectionKey.OP_WRITE : 写
* 如果需要监听多个可以通过竖线串起来
*
*/
socketChannel.register(selector, SelectionKey.OP_ACCEPT);
// 通过循环式的获取选择器上已经"准备就绪"的事件
// 当选择器上有"准备就绪"的状态时,他的select值会大于0
while(selector.select() > 0){
// 所以所有准备就绪的选择器
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
if (key.isAcceptable()){
// 获取一个阻塞式的Channle
SocketChannel sChannel = socketChannel.accept();
// 设置他为非阻塞式
sChannel.configureBlocking(false);
// 注册到选择器 监听读操作
sChannel.register(selector,SelectionKey.OP_READ);
}else if(key.isReadable()){
// 从选择器中获取当前Channel
SocketChannel sChannel = (SocketChannel) key.channel();
ByteBuffer buf = ByteBuffer.allocate(1024);
int len = 0;
// 读取客户端发来的消息
while((len = sChannel.read(buf)) > 0){
buf.flip();
receMsg = new String(buf.array(),0,len);
System.out.println("来自客户端的消息 : " + receMsg);
buf.clear();
}
// 切换到监听写模式
sChannel.register(selector,SelectionKey.OP_WRITE);
}else if (key.isWritable()){
SocketChannel sChannel = (SocketChannel) key.channel();
if ("".equals(receMsg)){
sChannel.register(selector,SelectionKey.OP_READ);
}else{
ByteBuffer buf = ByteBuffer.allocate(1024);
// String msg = receMsg + " -- Hello ";
// buf.put(msg.getBytes());
// 从控制台写入消息并发出去
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
buf.put(scanner.next().getBytes());
break;
}
buf.flip();
receMsg = "";
sChannel.write(buf);
}
}
iterator.remove();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
客户端
package com.xbb.demo.twoway;
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;
import java.util.Scanner;
/**
* 客户端
*/
public class NonClientSocket {
public static void main(String[] args) {
try(
// 创建Socket客户端
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("192.168.93.44",9999));
){
String responseMsg = "";
boolean isFirst = true;
// 切换非阻塞模式
socketChannel.configureBlocking(false);
// 创建选择器
Selector selector = Selector.open();
// 注册选择器,监听读写
socketChannel.register(selector, SelectionKey.OP_WRITE,SelectionKey.OP_READ);
while(selector.select() > 0){
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while(iterator.hasNext()){
SelectionKey next = iterator.next();
// 写操作,发送消息
if (next.isWritable()){
socketChannel.register(selector,SelectionKey.OP_READ);
// 第一个消息由客户端发出
if(isFirst){
isFirst = false;
SocketChannel sChannel = (SocketChannel) next.channel();
sChannel.configureBlocking(false);
// 本次发送出去消息后切换为读模式,读服务器回馈的消息
ByteBuffer buf = ByteBuffer.allocate(1024);
// 从控制台输入消息并发出去
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
buf.put(scanner.next().getBytes());
break;
}
buf.flip();
sChannel.write(buf);
buf.clear();
// 如果不是第一次,判断是否收到对方回馈的消息
}else{
if(!"".equals(responseMsg)){
SocketChannel sChannel = (SocketChannel) next.channel();
sChannel.configureBlocking(false);
ByteBuffer buf = ByteBuffer.allocate(1024);
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
buf.put(scanner.next().getBytes());
break;
}
buf.flip();
sChannel.write(buf);
buf.clear();
}
}
responseMsg = "";
}else if (next.isReadable()){
SocketChannel sChannel = (SocketChannel)next.channel();
ByteBuffer buf = ByteBuffer.allocate(1024);
int len = 0;
while((len = sChannel.read(buf)) > 0){
buf.flip();
responseMsg = new String(buf.array(),0,len);
System.out.println("来自服务端的消息 : " + responseMsg);
buf.clear();
}
socketChannel.register(selector,SelectionKey.OP_WRITE);
}
iterator.remove();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}