用 Java Nio 实现一个和Netty一样的功能Server端和client端 并给每行代码写上注释
时间: 2024-05-03 08:16:49 浏览: 214
以下是使用 Java NIO 实现 Server 和 Client 的示例程序,注释已经尽量详细了,如果还有疑问可以留言。
Server.java
```java
import java.io.IOException;
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;
public class Server {
private static final int BUF_SIZE = 1024;
private static final int PORT = 8080;
private static final int TIMEOUT = 3000;
public static void main(String[] args) {
selector();
}
public static void selector() {
Selector selector = null;
ServerSocketChannel serverSocketChannel = null;
try {
// 打开一个Selector
selector = Selector.open();
// 打开一个ServerSocketChannel
serverSocketChannel = ServerSocketChannel.open();
// 配置为非阻塞模式
serverSocketChannel.configureBlocking(false);
// 绑定端口
serverSocketChannel.socket().bind(new InetSocketAddress(PORT));
// 注册OP_ACCEPT事件
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
// 阻塞等待事件
if (selector.select(TIMEOUT) == 0) {
System.out.println("等待中...");
continue;
}
// 获取所有已就绪的事件
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
// 如果是连接事件
if (key.isAcceptable()) {
handleAccept(key);
}
// 如果是读事件
if (key.isReadable()) {
handleRead(key);
}
// 如果是写事件
if (key.isWritable() && key.isValid()) {
handleWrite(key);
}
// 删除已处理的事件
iterator.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (selector != null) {
selector.close();
}
if (serverSocketChannel != null) {
serverSocketChannel.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void handleAccept(SelectionKey key) throws IOException {
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
// 接受连接
SocketChannel socketChannel = serverSocketChannel.accept();
// 配置为非阻塞模式
socketChannel.configureBlocking(false);
// 注册读事件
socketChannel.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocateDirect(BUF_SIZE));
}
public static void handleRead(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = (ByteBuffer) key.attachment();
buffer.clear();
int len;
while ((len = socketChannel.read(buffer)) > 0) {
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
System.out.println("收到消息:" + new String(bytes));
}
if (len == -1) {
socketChannel.close();
} else {
// 注册写事件
socketChannel.register(key.selector(), SelectionKey.OP_WRITE, buffer);
}
}
public static void handleWrite(SelectionKey key) throws IOException {
ByteBuffer buffer = (ByteBuffer) key.attachment();
buffer.flip();
SocketChannel socketChannel = (SocketChannel) key.channel();
socketChannel.write(buffer);
if (!buffer.hasRemaining()) {
socketChannel.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocateDirect(BUF_SIZE));
}
}
}
```
Client.java
```java
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
public class Client {
private static final int BUF_SIZE = 1024;
private static final int PORT = 8080;
private static final String HOST = "localhost";
public static void main(String[] args) {
try (SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(HOST, PORT))) {
// 配置为非阻塞模式
socketChannel.configureBlocking(false);
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String msg = scanner.nextLine();
ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
// 发送消息
socketChannel.write(buffer);
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
```
阅读全文