一个可运行的简单NIO实例,首先是一个抽象的服务端类AbstractNIOServer
public abstract class AbstractNIOServer implements Runnable {
// 要监听的端口号
protected int port;
// 生成一个信号监视器
protected Selector s;
public AbstractNIOServer(int port) {
this.port = port;
try {
s = Selector.open();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
// 生成一个ServerScoket通道的实例对象,用于侦听可能发生的IO事件
ServerSocketChannel ssc = ServerSocketChannel.open();
// 将该通道设置为异步方式
ssc.configureBlocking(false);
// 绑定到一个指定的端口
ssc.socket().bind(new InetSocketAddress(port));
// 注册特定类型的事件到信号监视器上
ssc.register(s, SelectionKey.OP_ACCEPT);
System.out.println("The server has been launched...");
while (true) {
// 将会阻塞执行,直到有事件发生
s.select();
Iterator<SelectionKey> it = s.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
// key定义了四种不同形式的操作
switch (key.readyOps()) {
case SelectionKey.OP_ACCEPT:
dealwithAccept(key);
break;
case SelectionKey.OP_CONNECT:
break;
case SelectionKey.OP_READ:
dealwithRead(key);
break;
case SelectionKey.OP_WRITE:
break;
}
// 处理结束后移除当前事件,以免重复处理
it.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 处理接收连接的事件
public abstract void dealwithAccept(SelectionKey key);
// 处理客户端发来的消息,处理读事件
public abstract void dealwithRead(SelectionKey key);
}
服务端实现类SynServer
class SynServer extends AbstractNIOServer {
public SynServer(int port) {
super(port);
}
// 读缓冲区
private ByteBuffer r_bBuf = ByteBuffer.allocate(1024);
private ByteBuffer w_bBuf;
// 处理接收连接的事件
@Override
public void dealwithAccept(SelectionKey key) {
try {
System.out.println("新的客户端请求连接...");
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel sc = server.accept();
sc.configureBlocking(false);
// 注册读事件
sc.register(s, SelectionKey.OP_READ);
System.out.println("客户端连接成功...");
// 更新最新域模型
} catch (IOException e) {
e.printStackTrace();
}
}
// 处理客户端发来的消息,处理读事件
@Override
public void dealwithRead(SelectionKey key) {
try {
SocketChannel sc = (SocketChannel) key.channel();
System.out.println("读入数据");
r_bBuf.clear();
// 将字节序列从此通道中读入给定的缓冲区r_bBuf
sc.read(r_bBuf);
r_bBuf.flip();
String msg = Charset.forName("UTF-8").decode(r_bBuf).toString();
if (msg.equalsIgnoreCase("time")) {
w_bBuf = ByteBuffer.wrap(getCurrentTime().getBytes("UTF-8"));
sc.write(w_bBuf);
w_bBuf.clear();
} else if (msg.equalsIgnoreCase("bye")) {
sc.write(ByteBuffer.wrap("已经与服务器断开连接".getBytes("UTF-8")));
sc.socket().close();
} else {
sc.write(ByteBuffer.wrap(msg.getBytes("UTF-8")));
}
System.out.println(msg);
System.out.println("处理完毕...");
r_bBuf.clear();
try {
Thread.currentThread();
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private String getCurrentTime() {
Calendar date = Calendar.getInstance();
String time = "服务器当前时间:" + date.get(Calendar.YEAR) + "-" + date.get(Calendar.MONTH) + 1 + "-"
+ date.get(Calendar.DATE) + " " + date.get(Calendar.HOUR) + ":" + date.get(Calendar.MINUTE) + ":"
+ date.get(Calendar.SECOND);
return time;
}
}
服务端测试类TestServer
public class TestServer {
public static void main(String[] args) {
Executors.newSingleThreadExecutor().submit(new SynServer(1982));
// new Thread().start();
}
}
客户端测试类TestClient
public class TestClient {
public static void main(String[] args) {
new MiniClient("localhost", 1982);
}
}
class MiniClient {
private SocketChannel sc;
private ByteBuffer w_bBuf;
private ByteBuffer r_bBuf = ByteBuffer.allocate(1024);
public MiniClient(String host, int port) {
try {
InetSocketAddress remote = new InetSocketAddress(host, port);
sc = SocketChannel.open();
sc.connect(remote);
if (sc.finishConnect()) {
System.out.println("已经与服务器成功建立连接...");
}
while (true) {
if (!sc.socket().isConnected()) {
System.out.println("已经与服务器失去了连接...");
return;
}
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
System.out.println("读入一行数据,开始发送...");
w_bBuf = ByteBuffer.wrap(str.getBytes("UTF-8"));
// 将缓冲区中数据写入通道
sc.write(w_bBuf);
System.out.println("数据发送成功...");
w_bBuf.clear();
System.out.println("接收服务器端响应消息...");
try {
Thread.currentThread();
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
r_bBuf.clear();
// 将字节序列从此通道中读入给定的缓冲区r_bBuf
sc.read(r_bBuf);
r_bBuf.flip();
String msg = Charset.forName("UTF-8").decode(r_bBuf).toString();
System.out.println(msg);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}