用NIO技术替代线程池技术改写Knock Knock游戏的客户机/服务器设计,请给出代码
时间: 2024-03-01 13:56:05 浏览: 145
好的,以下是使用NIO技术替代线程池技术改写Knock Knock游戏的客户机/服务器设计的代码示例:
服务器端代码:
```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 KnockKnockServer {
private static final int BUFFER_SIZE = 1024;
private static final int TIMEOUT = 3000;
public static void main(String[] args) throws IOException {
// 创建选择器
Selector selector = Selector.open();
// 创建服务器套接字通道并绑定端口
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(8080));
serverSocketChannel.configureBlocking(false);
// 将服务器套接字通道注册到选择器上并指定感兴趣的事件为接收连接
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
// 选择器等待通道就绪
if (selector.select(TIMEOUT) == 0) {
System.out.println(".");
continue;
}
// 获取已经就绪的通道的 SelectionKey 集合并遍历
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
if (selectionKey.isAcceptable()) {
// 接收连接请求并注册读事件
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
System.out.println("Accepted connection from " + socketChannel);
} else if (selectionKey.isReadable()) {
// 读取客户端数据
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
int bytesRead = socketChannel.read(buffer);
if (bytesRead == -1) {
// 客户端已经关闭连接
selectionKey.cancel();
System.out.println("Closed connection from " + socketChannel);
} else if (bytesRead > 0) {
// 处理客户端数据并响应
buffer.flip();
String request = new String(buffer.array(), 0, bytesRead).trim();
String response = processRequest(request);
buffer = ByteBuffer.wrap(response.getBytes());
socketChannel.write(buffer);
}
}
// 从已经就绪的 SelectionKey 集合中移除当前处理的 SelectionKey
iterator.remove();
}
}
}
private static String processRequest(String request) {
String[] jokes = {
"Knock, knock. Who’s there? Boo. Boo who? Don’t cry, it’s only a joke.",
"Knock, knock. Who’s there? Tank. Tank who? You’re welcome.",
"Knock, knock. Who’s there? Amish. Amish who? Really? You don’t look like a shoe!",
"Knock, knock. Who’s there? Little old lady. Little old lady who? I didn’t know you could yodel!",
"Knock, knock. Who’s there? Harry. Harry who? Harry up and answer the door!",
};
if ("Knock, knock.".equals(request)) {
return "Who’s there?";
} else if (request.endsWith("?")) {
int index = (int) (Math.random() * jokes.length);
return jokes[index];
} else {
return "You’re supposed to say \"Knock, knock.\"!";
}
}
}
```
客户端代码:
```java
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
public class KnockKnockClient {
private static final int BUFFER_SIZE = 1024;
public static void main(String[] args) throws IOException {
// 创建套接字通道并连接服务器
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("localhost", 8080));
// 读取用户输入并发送给服务器
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("You: ");
String request = scanner.nextLine();
if ("quit".equals(request)) {
break;
}
ByteBuffer buffer = ByteBuffer.wrap(request.getBytes());
socketChannel.write(buffer);
// 读取服务器响应并输出到控制台
buffer = ByteBuffer.allocate(BUFFER_SIZE);
int bytesRead = socketChannel.read(buffer);
buffer.flip();
String response = new String(buffer.array(), 0, bytesRead).trim();
System.out.println("Server: " + response);
}
// 关闭套接字通道
socketChannel.close();
}
}
```
阅读全文