正在显示
17 个修改的文件
包含
583 行增加
和
0 行删除
.gitignore
0 → 100644
1 | +### IntelliJ IDEA ### | ||
2 | +out/ | ||
3 | +!**/src/main/**/out/ | ||
4 | +!**/src/test/**/out/ | ||
5 | + | ||
6 | +### Eclipse ### | ||
7 | +.apt_generated | ||
8 | +.classpath | ||
9 | +.factorypath | ||
10 | +.project | ||
11 | +.settings | ||
12 | +.springBeans | ||
13 | +.sts4-cache | ||
14 | +bin/ | ||
15 | +!**/src/main/**/bin/ | ||
16 | +!**/src/test/**/bin/ | ||
17 | + | ||
18 | +### NetBeans ### | ||
19 | +/nbproject/private/ | ||
20 | +/nbbuild/ | ||
21 | +/dist/ | ||
22 | +/nbdist/ | ||
23 | +/.nb-gradle/ | ||
24 | + | ||
25 | +### VS Code ### | ||
26 | +.vscode/ | ||
27 | + | ||
28 | +### Mac OS ### | ||
29 | +.DS_Store |
.idea/.gitignore
0 → 100644
.idea/compiler.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project version="4"> | ||
3 | + <component name="CompilerConfiguration"> | ||
4 | + <annotationProcessing> | ||
5 | + <profile name="Maven default annotation processors profile" enabled="true"> | ||
6 | + <sourceOutputDir name="target/generated-sources/annotations" /> | ||
7 | + <sourceTestOutputDir name="target/generated-test-sources/test-annotations" /> | ||
8 | + <outputRelativeToContentRoot value="true" /> | ||
9 | + <module name="Software_Architecture_Experiment_onetwo" /> | ||
10 | + </profile> | ||
11 | + </annotationProcessing> | ||
12 | + </component> | ||
13 | +</project> |
.idea/encodings.xml
0 → 100644
.idea/jarRepositories.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project version="4"> | ||
3 | + <component name="RemoteRepositoriesConfiguration"> | ||
4 | + <remote-repository> | ||
5 | + <option name="id" value="central" /> | ||
6 | + <option name="name" value="Central Repository" /> | ||
7 | + <option name="url" value="https://repo.maven.apache.org/maven2" /> | ||
8 | + </remote-repository> | ||
9 | + <remote-repository> | ||
10 | + <option name="id" value="central" /> | ||
11 | + <option name="name" value="Maven Central repository" /> | ||
12 | + <option name="url" value="https://repo1.maven.org/maven2" /> | ||
13 | + </remote-repository> | ||
14 | + <remote-repository> | ||
15 | + <option name="id" value="jboss.community" /> | ||
16 | + <option name="name" value="JBoss Community repository" /> | ||
17 | + <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" /> | ||
18 | + </remote-repository> | ||
19 | + </component> | ||
20 | +</project> |
.idea/misc.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project version="4"> | ||
3 | + <component name="ExternalStorageConfigurationManager" enabled="true" /> | ||
4 | + <component name="MavenProjectsManager"> | ||
5 | + <option name="originalFiles"> | ||
6 | + <list> | ||
7 | + <option value="$PROJECT_DIR$/pom.xml" /> | ||
8 | + </list> | ||
9 | + </option> | ||
10 | + </component> | ||
11 | + <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK"> | ||
12 | + <output url="file://$PROJECT_DIR$/out" /> | ||
13 | + </component> | ||
14 | + <component name="accountSettings"> | ||
15 | + <option name="activeRegion" value="us-east-1" /> | ||
16 | + <option name="recentlyUsedRegions"> | ||
17 | + <list> | ||
18 | + <option value="us-east-1" /> | ||
19 | + </list> | ||
20 | + </option> | ||
21 | + </component> | ||
22 | +</project> |
.idea/modules.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project version="4"> | ||
3 | + <component name="ProjectModuleManager"> | ||
4 | + <modules> | ||
5 | + <module fileurl="file://$PROJECT_DIR$/Software_Architecture_Experiment_onetwo.iml" filepath="$PROJECT_DIR$/Software_Architecture_Experiment_onetwo.iml" /> | ||
6 | + </modules> | ||
7 | + </component> | ||
8 | +</project> |
.idea/vcs.xml
0 → 100644
Software_Architecture_Experiment_onetwo.iml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<module type="JAVA_MODULE" version="4"> | ||
3 | + <component name="AdditionalModuleElements"> | ||
4 | + <content url="file://$MODULE_DIR$" dumb="true"> | ||
5 | + <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> | ||
6 | + </content> | ||
7 | + </component> | ||
8 | +</module> |
pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
5 | + <modelVersion>4.0.0</modelVersion> | ||
6 | + | ||
7 | + <groupId>com.dyj</groupId> | ||
8 | + <artifactId>Software_Architecture_Experiment_onetwo</artifactId> | ||
9 | + <version>1.0-SNAPSHOT</version> | ||
10 | + <dependencies> | ||
11 | + <dependency> | ||
12 | + <groupId>io.netty</groupId> | ||
13 | + <artifactId>netty-all</artifactId> | ||
14 | + <version>4.1.92.Final</version> | ||
15 | + <scope>compile</scope> | ||
16 | + </dependency> | ||
17 | + </dependencies> | ||
18 | + | ||
19 | + | ||
20 | + <properties> | ||
21 | + <maven.compiler.source>17</maven.compiler.source> | ||
22 | + <maven.compiler.target>17</maven.compiler.target> | ||
23 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
24 | + </properties> | ||
25 | + | ||
26 | +</project> |
src/main/java/one/Client.java
0 → 100644
1 | +package one; | ||
2 | + | ||
3 | +import java.net.*; | ||
4 | +import java.io.*; | ||
5 | +import java.util.Scanner; | ||
6 | + | ||
7 | +public class Client { | ||
8 | + public static void main(String[] args) { | ||
9 | + try { | ||
10 | + Socket socket = new Socket("localhost", 8888); | ||
11 | + System.out.println("连接服务器成功!"); | ||
12 | + Scanner scanner = new Scanner(System.in); | ||
13 | + String input; | ||
14 | + | ||
15 | + | ||
16 | + while (true){ | ||
17 | + if ((input = scanner.next()) != null){ | ||
18 | + | ||
19 | + PrintWriter writer = new PrintWriter(socket.getOutputStream()); | ||
20 | + writer.println(input); | ||
21 | + writer.flush(); | ||
22 | + System.out.println("已发送命令:"+input); | ||
23 | + if(input.equals("exit")){ | ||
24 | + break; | ||
25 | + } | ||
26 | + } | ||
27 | + | ||
28 | + | ||
29 | + BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); | ||
30 | + String time = reader.readLine(); | ||
31 | + // 处理读取到的数据 | ||
32 | + System.out.println("收到服务器时间:" + time); | ||
33 | + | ||
34 | +// String time = reader.readLine(); | ||
35 | +// System.out.println("收到服务器时间:" + time); | ||
36 | + } | ||
37 | + socket.close(); | ||
38 | + } catch (IOException e) { | ||
39 | + e.printStackTrace(); | ||
40 | + } | ||
41 | + } | ||
42 | +} |
src/main/java/one/Server.java
0 → 100644
1 | +package one; | ||
2 | + | ||
3 | +import java.net.*; | ||
4 | +import java.io.*; | ||
5 | +import java.util.Date; | ||
6 | + | ||
7 | +public class Server { | ||
8 | + public static void main(String[] args) { | ||
9 | + try { | ||
10 | + ServerSocket serverSocket = new ServerSocket(8888); | ||
11 | + System.out.println("服务器已启动,等待客户端连接..."); | ||
12 | + Socket socket = null; | ||
13 | + while (true) { | ||
14 | + if (socket == null){ | ||
15 | + socket = serverSocket.accept(); | ||
16 | + System.out.println("客户端连接成功!"); | ||
17 | + } | ||
18 | + | ||
19 | + BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); | ||
20 | + String command = reader.readLine(); | ||
21 | + if(command != null && command.equals("exit")){ | ||
22 | + break; | ||
23 | + } | ||
24 | + System.out.println("收到客户端命令:" + command); | ||
25 | + | ||
26 | + if (command != null){ | ||
27 | + if (command.equals("get_time")) { | ||
28 | + PrintWriter writer = new PrintWriter(socket.getOutputStream()); | ||
29 | + writer.println(new Date(System.currentTimeMillis())); | ||
30 | + writer.flush(); | ||
31 | + System.out.println("服务器时间已发送!"); | ||
32 | + }else { | ||
33 | + PrintWriter writer = new PrintWriter(socket.getOutputStream()); | ||
34 | + writer.println("该命令错误,请输入正确命令!"); | ||
35 | + writer.flush(); | ||
36 | + System.out.println("命令错误!!!"); | ||
37 | + } | ||
38 | + } | ||
39 | + | ||
40 | + } | ||
41 | + socket.close(); | ||
42 | + } catch (IOException e) { | ||
43 | + e.printStackTrace(); | ||
44 | + | ||
45 | + } | ||
46 | + } | ||
47 | +} |
src/main/java/two/Client.java
0 → 100644
1 | +package two; | ||
2 | + | ||
3 | +import java.io.IOException; | ||
4 | +import java.net.InetSocketAddress; | ||
5 | +import java.nio.ByteBuffer; | ||
6 | +import java.nio.channels.SocketChannel; | ||
7 | +import java.util.Scanner; | ||
8 | + | ||
9 | +public class Client { | ||
10 | + private static final int BUFFER_SIZE = 1024; | ||
11 | + private static final String HOST = "localhost"; | ||
12 | + private static final int PORT = 8888; | ||
13 | + | ||
14 | + public static void main(String[] args) { | ||
15 | + try { | ||
16 | + SocketChannel clientChannel = SocketChannel.open(); | ||
17 | + clientChannel.configureBlocking(false); | ||
18 | + clientChannel.connect(new InetSocketAddress(HOST, PORT)); | ||
19 | + | ||
20 | + while (!clientChannel.finishConnect()) { | ||
21 | + // wait until connection is established | ||
22 | + } | ||
23 | + | ||
24 | + System.out.println("Connected to server " + HOST + ":" + PORT); | ||
25 | + System.out.println("Enter your name:"); | ||
26 | + | ||
27 | + Scanner scanner = new Scanner(System.in); | ||
28 | + String name = scanner.nextLine(); | ||
29 | + ByteBuffer buffer = ByteBuffer.wrap(name.getBytes()); | ||
30 | + clientChannel.write(buffer); | ||
31 | + | ||
32 | + new Thread(() -> { | ||
33 | + while (true) { | ||
34 | + try { | ||
35 | + ByteBuffer receiveBuffer = ByteBuffer.allocate(BUFFER_SIZE); | ||
36 | + int bytesRead = clientChannel.read(receiveBuffer); | ||
37 | + if (bytesRead > 0) { | ||
38 | + String message = new String(receiveBuffer.array()).trim(); | ||
39 | + System.out.println(message); | ||
40 | + } | ||
41 | + } catch (IOException e) { | ||
42 | + e.printStackTrace(); | ||
43 | + } | ||
44 | + } | ||
45 | + }).start(); | ||
46 | + | ||
47 | + while (true) { | ||
48 | + String message = scanner.nextLine(); | ||
49 | + buffer = ByteBuffer.wrap(message.getBytes()); | ||
50 | + clientChannel.write(buffer); | ||
51 | + } | ||
52 | + } catch (IOException e) { | ||
53 | + e.printStackTrace(); | ||
54 | + } | ||
55 | + } | ||
56 | +} |
src/main/java/two/NIOClient.java
0 → 100644
1 | +package two; | ||
2 | + | ||
3 | +import java.io.IOException; | ||
4 | +import java.net.InetSocketAddress; | ||
5 | +import java.nio.ByteBuffer; | ||
6 | +import java.nio.channels.SocketChannel; | ||
7 | +import java.util.Scanner; | ||
8 | + | ||
9 | +public class NIOClient { | ||
10 | + public void start(String hostname, int port) throws IOException { | ||
11 | + // 创建SocketChannel | ||
12 | + SocketChannel socketChannel = SocketChannel.open(); | ||
13 | + socketChannel.configureBlocking(false); | ||
14 | + socketChannel.connect(new InetSocketAddress(hostname, port)); | ||
15 | + | ||
16 | + // 等待连接完成 | ||
17 | + while (!socketChannel.finishConnect()) { | ||
18 | + // do nothing | ||
19 | + } | ||
20 | + | ||
21 | + System.out.println("Connected to server " + socketChannel.getRemoteAddress()); | ||
22 | + | ||
23 | + // 循环读取用户输入,并发送到服务器 | ||
24 | + Scanner scanner = new Scanner(System.in); | ||
25 | + | ||
26 | + new Thread(() -> { | ||
27 | + while (true) { | ||
28 | + try { | ||
29 | + // 读取服务器发送的消息 | ||
30 | + ByteBuffer readBuffer = ByteBuffer.allocate(1024); | ||
31 | + int numRead = socketChannel.read(readBuffer); | ||
32 | + if (numRead > 0) { | ||
33 | + String receivedMessage = new String(readBuffer.array(), 0, numRead).trim(); | ||
34 | + System.out.println("Received message from server: " + receivedMessage); | ||
35 | + } | ||
36 | + } catch (IOException e) { | ||
37 | + e.printStackTrace(); | ||
38 | + } | ||
39 | + } | ||
40 | + }).start(); | ||
41 | + | ||
42 | + while (true) { | ||
43 | + if (scanner.hasNext()){ | ||
44 | + String message = scanner.nextLine(); | ||
45 | + ByteBuffer buffer = ByteBuffer.wrap(message.getBytes()); | ||
46 | + socketChannel.write(buffer); | ||
47 | + } | ||
48 | + } | ||
49 | + | ||
50 | + } | ||
51 | + | ||
52 | + public static void main(String[] args) throws IOException { | ||
53 | + NIOClient client = new NIOClient(); | ||
54 | + client.start("localhost", 8888); | ||
55 | + } | ||
56 | +} |
src/main/java/two/NIOServer.java
0 → 100644
1 | +package two; | ||
2 | + | ||
3 | +import java.io.IOException; | ||
4 | +import java.net.InetSocketAddress; | ||
5 | +import java.nio.ByteBuffer; | ||
6 | +import java.nio.channels.SelectionKey; | ||
7 | +import java.nio.channels.Selector; | ||
8 | +import java.nio.channels.ServerSocketChannel; | ||
9 | +import java.nio.channels.SocketChannel; | ||
10 | +import java.util.HashMap; | ||
11 | +import java.util.Iterator; | ||
12 | +import java.util.Map; | ||
13 | + | ||
14 | +public class NIOServer { | ||
15 | + private Selector selector; | ||
16 | + private Map<SocketChannel, String> clients = new HashMap<>(); | ||
17 | + | ||
18 | + public void start(int port) throws IOException { | ||
19 | + // 创建ServerSocketChannel | ||
20 | + ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); | ||
21 | + serverSocketChannel.socket().bind(new InetSocketAddress(port)); | ||
22 | + serverSocketChannel.configureBlocking(false); | ||
23 | + | ||
24 | + // 创建Selector | ||
25 | + selector = Selector.open(); | ||
26 | + | ||
27 | + // 注册ServerSocketChannel到Selector上,监听ACCEPT事件 | ||
28 | + serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); | ||
29 | + | ||
30 | + System.out.println("Server started..."); | ||
31 | + | ||
32 | + // 循环处理事件 | ||
33 | + while (true) { | ||
34 | + // 调用select方法阻塞,等待事件发生 | ||
35 | + selector.select(); | ||
36 | + | ||
37 | + Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator(); | ||
38 | + while (keyIterator.hasNext()) { | ||
39 | + SelectionKey key = keyIterator.next(); | ||
40 | + keyIterator.remove(); | ||
41 | + | ||
42 | + if (key.isAcceptable()) { // 处理ACCEPT事件 | ||
43 | + handleAccept(key); | ||
44 | + } else if (key.isReadable()) { // 处理READ事件 | ||
45 | + handleRead(key); | ||
46 | + } | ||
47 | + } | ||
48 | + } | ||
49 | + } | ||
50 | + | ||
51 | + private void handleAccept(SelectionKey key) throws IOException { | ||
52 | + // 获取ServerSocketChannel | ||
53 | + ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); | ||
54 | + | ||
55 | + // 接受客户端连接 | ||
56 | + SocketChannel socketChannel = serverSocketChannel.accept(); | ||
57 | + socketChannel.configureBlocking(false); | ||
58 | + | ||
59 | + // 注册SocketChannel到Selector上,监听READ事件 | ||
60 | + socketChannel.register(selector, SelectionKey.OP_READ); | ||
61 | + | ||
62 | + System.out.println("Client " + socketChannel.getRemoteAddress() + " connected."); | ||
63 | + | ||
64 | + // 将新连接的客户端添加到clients列表中 | ||
65 | + clients.put(socketChannel, socketChannel.getRemoteAddress().toString()); | ||
66 | + } | ||
67 | + | ||
68 | + private void handleRead(SelectionKey key) throws IOException { | ||
69 | + // 获取SocketChannel | ||
70 | + SocketChannel socketChannel = (SocketChannel) key.channel(); | ||
71 | + | ||
72 | + // 读取数据 | ||
73 | + ByteBuffer buffer = ByteBuffer.allocate(1024); | ||
74 | + int numRead = socketChannel.read(buffer); | ||
75 | + if (numRead == -1) { // 客户端关闭连接 | ||
76 | + key.cancel(); | ||
77 | + clients.remove(socketChannel); | ||
78 | + System.out.println("Client " + socketChannel.getRemoteAddress() + " disconnected."); | ||
79 | + socketChannel.close(); | ||
80 | + return; | ||
81 | + } | ||
82 | + | ||
83 | + // 将数据转发给其他客户端 | ||
84 | + String message = new String(buffer.array(), 0, numRead).trim(); | ||
85 | + System.out.println("Received message from " + socketChannel.getRemoteAddress() + ": " + message); | ||
86 | + for (SocketChannel client : clients.keySet()) { | ||
87 | + if (client != socketChannel) { | ||
88 | + ByteBuffer writeBuffer = ByteBuffer.wrap(message.getBytes()); | ||
89 | + client.write(writeBuffer); | ||
90 | + } | ||
91 | + } | ||
92 | + } | ||
93 | + | ||
94 | + public static void main(String[] args) throws IOException { | ||
95 | + NIOServer server = new NIOServer(); | ||
96 | + server.start(8888); | ||
97 | + } | ||
98 | +} |
src/main/java/two/Server.java
0 → 100644
1 | +package two; | ||
2 | + | ||
3 | +import java.io.IOException; | ||
4 | +import java.net.InetSocketAddress; | ||
5 | +import java.nio.ByteBuffer; | ||
6 | +import java.nio.channels.SelectionKey; | ||
7 | +import java.nio.channels.Selector; | ||
8 | +import java.nio.channels.ServerSocketChannel; | ||
9 | +import java.nio.channels.SocketChannel; | ||
10 | +import java.util.HashMap; | ||
11 | +import java.util.Iterator; | ||
12 | +import java.util.Map; | ||
13 | + | ||
14 | +public class Server { | ||
15 | + private static final int BUFFER_SIZE = 1024; | ||
16 | + private static final int PORT = 8888; | ||
17 | + | ||
18 | + private Selector selector; | ||
19 | + private Map<SocketChannel, String> clientMap = new HashMap<>(); | ||
20 | + | ||
21 | + public static void main(String[] args) { | ||
22 | + Server server = new Server(); | ||
23 | + server.startServer(); | ||
24 | + } | ||
25 | + | ||
26 | + public void startServer() { | ||
27 | + try { | ||
28 | + selector = Selector.open(); | ||
29 | + ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); | ||
30 | + serverSocketChannel.configureBlocking(false); | ||
31 | + serverSocketChannel.socket().bind(new InetSocketAddress(PORT)); | ||
32 | + serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); | ||
33 | + System.out.println("Server started on port " + PORT); | ||
34 | + | ||
35 | + while (true) { | ||
36 | + int readyChannels = selector.select(); | ||
37 | + if (readyChannels == 0) { | ||
38 | + continue; | ||
39 | + } | ||
40 | + | ||
41 | + Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator(); | ||
42 | + while (keyIterator.hasNext()) { | ||
43 | + SelectionKey key = keyIterator.next(); | ||
44 | + | ||
45 | + if (key.isAcceptable()) { | ||
46 | + SocketChannel clientChannel = serverSocketChannel.accept(); | ||
47 | + clientChannel.configureBlocking(false); | ||
48 | + clientChannel.register(selector, SelectionKey.OP_READ); | ||
49 | + System.out.println("New client connected: " + clientChannel.getRemoteAddress()); | ||
50 | + clientMap.put(clientChannel, ""); | ||
51 | + } | ||
52 | + | ||
53 | + if (key.isReadable()) { | ||
54 | + SocketChannel clientChannel = (SocketChannel) key.channel(); | ||
55 | + ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); | ||
56 | + int bytesRead = clientChannel.read(buffer); | ||
57 | + if (bytesRead > 0) { | ||
58 | + String message = new String(buffer.array()).trim(); | ||
59 | + if (clientMap.get(clientChannel).equals("")) { | ||
60 | + clientMap.put(clientChannel, message); | ||
61 | + System.out.println("New user registered: " + message); | ||
62 | + broadcast(message + "上线啦 ", clientChannel); | ||
63 | + } else { | ||
64 | + System.out.println("Message received from " + clientMap.get(clientChannel) + ": " + message); | ||
65 | + broadcast(clientMap.get(clientChannel) + ": " + message, clientChannel); | ||
66 | + } | ||
67 | + } | ||
68 | + } | ||
69 | + | ||
70 | + keyIterator.remove(); | ||
71 | + } | ||
72 | + } | ||
73 | + } catch (IOException e) { | ||
74 | + e.printStackTrace(); | ||
75 | + } | ||
76 | + } | ||
77 | + | ||
78 | + private void broadcast(String message, SocketChannel senderChannel) throws IOException { | ||
79 | + | ||
80 | + for (SocketChannel clientChannel : clientMap.keySet()) { | ||
81 | + if (clientChannel != senderChannel) { | ||
82 | + System.out.println(clientChannel); | ||
83 | + //多个对象发送,每次都得载一个新的对象,不然就只能发送一次 | ||
84 | + ByteBuffer buffer = ByteBuffer.wrap(message.getBytes()); | ||
85 | + clientChannel.write(buffer); | ||
86 | + } | ||
87 | + } | ||
88 | + } | ||
89 | +} |
src/main/java/two/read.md
0 → 100644
1 | +# 代码流程 | ||
2 | +代码实现了一个基于Java NIO的C/S架构的简单聊天室,其中服务器端使用epoll模型,支持多个客户端连接,一个客户端发送消息,服务器会将消息转发到其他客户端并在其他客户端显示这条消息。 | ||
3 | + | ||
4 | +服务器端代码的实现流程如下: | ||
5 | + | ||
6 | +1. 创建Selector对象和ServerSocketChannel对象,并将ServerSocketChannel注册到Selector上,监听连接事件。 | ||
7 | + | ||
8 | +2. 进入主循环,调用Selector的select()方法等待事件发生。 | ||
9 | + | ||
10 | +3. 如果有事件发生,使用迭代器遍历SelectionKey集合,处理每个事件。 | ||
11 | + | ||
12 | +4. 如果是连接事件,使用ServerSocketChannel的accept()方法接受客户端连接,并将客户端的SocketChannel注册到Selector上,监听读事件。 | ||
13 | + | ||
14 | +5. 如果是读事件,使用SocketChannel的read()方法读取客户端发送的消息,并将其转发给其他客户端。 | ||
15 | + | ||
16 | +6. 处理完事件后,使用迭代器的remove()方法将SelectionKey从集合中删除。 | ||
17 | + | ||
18 | +7. 回到主循环,等待下一个事件。 | ||
19 | + | ||
20 | +客户端代码的实现流程如下: | ||
21 | + | ||
22 | +1. 创建SocketChannel对象,连接服务器。 | ||
23 | + | ||
24 | +2. 如果连接未完成,等待连接完成。 | ||
25 | + | ||
26 | +3. 读取用户输入的用户名,将其发送给服务器。 | ||
27 | + | ||
28 | +4. 创建一个新线程,使用SocketChannel的read()方法读取服务器发送的消息,并在控制台上显示。 | ||
29 | + | ||
30 | +5. 在主线程中,读取用户输入的消息,使用SocketChannel的write()方法将其发送给服务器。 | ||
31 | + | ||
32 | +服务器端代码的重点内容: | ||
33 | + | ||
34 | +1. 使用Selector模型实现了高效的I/O多路复用,支持同时处理多个客户端连接。 | ||
35 | + | ||
36 | +2. 使用ByteBuffer缓冲区实现了高效的读写操作。 | ||
37 | + | ||
38 | +3. 使用Map集合保存每个客户端的SocketChannel和用户名,实现了转发消息给其他客户端的功能。 | ||
39 | + | ||
40 | +4. 使用迭代器遍历SelectionKey集合,处理每个事件,实现了高效的事件处理。 | ||
41 | + | ||
42 | +客户端代码的重点内容: | ||
43 | + | ||
44 | +1. 使用SocketChannel实现了非阻塞式的I/O操作。 | ||
45 | + | ||
46 | +2. 使用ByteBuffer缓冲区实现了高效的读写操作。 | ||
47 | + | ||
48 | +3. 使用Scanner读取用户输入的消息,实现了用户与服务器的交互。 |
-
请 注册 或 登录 后发表评论