用NIO技术代替一客户一线程技术改写Echo项目的客户机/服务器设计,请给出代码
时间: 2024-03-01 14:55:59 浏览: 166
基于事件的_NIO_多线程服务器
以下是使用NIO技术改写Echo项目的客户机/服务器设计的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 NioEchoServer {
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 ssc = null;
try {
// 创建选择器
selector = Selector.open();
// 打开监听通道
ssc = ServerSocketChannel.open();
// 绑定端口
ssc.socket().bind(new InetSocketAddress(PORT));
// 设置为非阻塞模式
ssc.configureBlocking(false);
// 注册选择器并监听接受事件
ssc.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Server started and listen on port " + PORT + "...");
while (true) {
// 等待事件
if (selector.select(TIMEOUT) == 0) {
System.out.print(".");
continue;
}
// 获取事件集合
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
// 处理事件
handleKey(key);
iter.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (selector != null) {
selector.close();
}
if (ssc != null) {
ssc.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void handleKey(SelectionKey key) throws IOException {
if (key.isAcceptable()) {
// 处理接受事件
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(key.selector(), SelectionKey.OP_READ);
}
if (key.isReadable()) {
// 处理读事件
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
int len = sc.read(buf);
if (len > 0) {
buf.flip();
byte[] bytes = new byte[buf.remaining()];
buf.get(bytes);
String msg = new String(bytes, "UTF-8");
System.out.println("Server received: " + msg);
sc.register(key.selector(), SelectionKey.OP_WRITE);
// 将读取到的数据写回客户端
ByteBuffer writeBuf = ByteBuffer.wrap(bytes);
sc.write(writeBuf);
} else if (len == -1) {
System.out.println("Client closed...");
sc.close();
}
}
if (key.isWritable()) {
// 处理写事件
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buf = (ByteBuffer) key.attachment();
buf.flip();
sc.write(buf);
if (!buf.hasRemaining()) {
key.interestOps(SelectionKey.OP_READ);
}
buf.compact();
}
}
}
```
客户端代码:
```java
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class NioEchoClient {
private static final int BUF_SIZE = 1024;
private static final int PORT = 8080;
public static void main(String[] args) {
try {
// 打开通道
SocketChannel sc = SocketChannel.open();
// 设置为非阻塞模式
sc.configureBlocking(false);
// 连接服务器
sc.connect(new InetSocketAddress(PORT));
while (!sc.finishConnect()) {
System.out.print(".");
}
System.out.println("Client connected...");
// 发送数据
ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
buf.put("Hello, NIO!".getBytes());
buf.flip();
sc.write(buf);
// 接收数据
buf.clear();
int len = sc.read(buf);
if (len > 0) {
buf.flip();
byte[] bytes = new byte[buf.remaining()];
buf.get(bytes);
String msg = new String(bytes, "UTF-8");
System.out.println("Client received: " + msg);
}
// 关闭通道
sc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
```
以上代码示例中,服务器端使用Selector监听ACCEPT、READ和WRITE事件,客户端使用SocketChannel与服务器建立连接,并发送和接收数据。通过NIO技术,可以实现多个客户端连接共享少量线程的并发处理。
阅读全文