server
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
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.Set;
public class NIOServer {
public static void main(String[] args) throws Exception {
// 1. 获取 ServerSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 2. 获取 Selector 对象
Selector selector = Selector.open();
// 3. 绑定一个 ip 和 端口 6666, 在服务器端监听
serverSocketChannel.socket().bind(new InetSocketAddress(6666));
// 4. 设置为非阻塞
serverSocketChannel.configureBlocking(false);
// 5. 把 serverSocketChannel 注册到 selector 关心, 事件为 OP_ACCEPT
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
// 6. 循环等待客户端链接
while (true) {
// eg: 这里我们等待1秒,如果没有事件发生,就返回
if (selector.select(1000) == 0) {// eg: 没有事件发生
System.out.println("服务器等待了1秒, 无链接");
continue;
}
// eg: 如果返回的 大于0
// eg: 该集合是表示有 事件发生的集合
Set<SelectionKey> selectedKeys = selector.selectedKeys();
// eg: 通过 selectedKeys 可以反向获取 channel
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey selectionKey = keyIterator.next();
if (selectionKey.isAcceptable()) {
// accept() 是阻塞的,但是这里不会阻塞
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
// eg: 将 socketChannel 注册到 selector 上, 关注只读事件,关联一个 ByteBuffer
socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
}
if (selectionKey.isReadable()) {
// eg: 通过key 反向获取channel
SocketChannel channel = (SocketChannel) selectionKey.channel();
ByteBuffer attachment = (ByteBuffer) selectionKey.attachment();
int read = channel.read(attachment);
System.out.println("客户端发送来的数据:"+new String(attachment.array(),0, attachment.position()));
}
// eg: 手动从集合中移除 selectionKey, 防止重复提交
// selectedKeys.remove(selectionKey); 并发修改异常
keyIterator.remove();
}
}
}
}
client
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class NIOClient {
public static void main(String[] args) throws Exception {
// 1: 客户端通道
SocketChannel socketChannel = SocketChannel.open();
//2. 设置为非阻塞
socketChannel.configureBlocking(false);
//3. 链接服务器
InetSocketAddress inetSocketAddress = new InetSocketAddress("localhost", 6666);
//4. 链接
if(!socketChannel.connect(inetSocketAddress)) {
while (! socketChannel.finishConnect()) {
System.out.println("客户端链接需要时间...");
}
}
//4.1 如果链接成功,发送数据
String content = "helloworld";
ByteBuffer buffer = ByteBuffer.wrap(content.getBytes());
socketChannel.write(buffer);
//System.in.read();
}
}
网友评论