Java网络编程:同步与异步通信实现解析
立即解锁
发布时间: 2025-08-19 00:15:57 阅读量: 1 订阅数: 5 

### Java网络编程:同步与异步通信实现解析
#### 1. 客户端与服务器交互基础
在开发客户端和服务器应用程序时,了解它们之间的交互方式至关重要。以下是一个简单的聊天服务器和客户端的交互示例。
当服务器启动后,再启动客户端应用程序,客户端会输出:
```
Connected to Chat Server
Waiting for message from the server ...
```
服务器则会显示:
```
Chat Server started
Waiting for request ...
Connected to Client
>
```
当在服务器端输入消息 “Hello” 时,服务器输出:
```
> Hello
Sent: Hello
Waiting for message from client ...
```
客户端会显示:
```
Message: Hello
>
```
接着在客户端输入回复 “Hi!”,客户端输出:
```
> Hi!
Sent: Hi!
Waiting for message from the server ...
```
服务器显示:
```
Message: Hi!
>
```
这个交互过程可以一直持续,直到任一方输入 “quit” 命令。不过,如果输入的消息超过 64 字节的缓冲区限制,会抛出 `BufferOverflowException` 异常。为避免此问题,可以将 `sendFixedLengthMessage` 方法替换为 `sendMessage` 方法,将 `receiveFixedLengthMessage` 方法替换为 `receiveMessage` 方法。
#### 2. HelperMethods 类
`HelperMethods` 类包含了之前使用的发送和接收消息的方法,这些方法被声明为静态,方便访问。
以下是固定长度消息的发送和接收方法:
```java
public class HelperMethods {
public static void sendFixedLengthMessage(
SocketChannel socketChannel, String message) {
try {
ByteBuffer buffer = ByteBuffer.allocate(64);
buffer.put(message.getBytes());
buffer.flip();
while (buffer.hasRemaining()) {
socketChannel.write(buffer);
}
System.out.println("Sent: " + message);
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static String receiveFixedLengthMessage(
SocketChannel socketChannel) {
String message = "";
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(64);
socketChannel.read(byteBuffer);
byteBuffer.flip();
while (byteBuffer.hasRemaining()) {
message += (char) byteBuffer.get();
}
} catch (IOException ex) {
ex.printStackTrace();
}
return message;
}
}
```
#### 3. 处理可变长度消息
可变长度消息的处理较为复杂,因为我们不知道消息的长度。不能仅仅因为缓冲区没有完全填满就认为消息结束。为了确定消息的结束位置,可以在消息前添加长度信息,或者在消息末尾添加特殊终止字符,这里选择了后者。
使用值 `0x00` 来标记消息的结束,因为它不可打印,用户不容易意外输入,并且在一些语言(如 C)中,字符串内部通常也是以这种方式终止的。
以下是处理可变长度消息的发送和接收方法:
```java
public class HelperMethods {
public static void sendMessage(
SocketChannel socketChannel, String message) {
try {
ByteBuffer buffer =
ByteBuffer.allocate(message.length() + 1);
buffer.put(message.getBytes());
buffer.put((byte) 0x00);
buffer.flip();
while (buffer.hasRemaining()) {
socketChannel.write(buffer);
}
System.out.println("Sent: " + message);
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static String receiveMessage(SocketChannel
socketChannel) {
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(16);
String message = "";
while (socketChannel.read(byteBuffer) > 0) {
char byteRead = 0x00;
byteBuffer.flip();
while (byteBuffer.hasRemaining()) {
byteRead = (char) byteBuffer.get();
if (byteRead == 0x00) {
break;
}
message += byteRead;
}
if (byteRead == 0x00) {
break;
}
byteBuffer.clear();
}
return message;
} catch (IOException ex) {
ex.printStackTrace();
}
return "";
}
}
```
#### 4. 运行聊天服务器/客户端应用程序
操作步骤如下:
1. 启动服务器,输出:
```
Chat Server started
Waiting for request ...
```
2. 启动客户端,输出:
```
Connected to Chat Server
Waiting for message from the server ...
```
3. 在服务器端输入消息,消息会发送到客户端。例如输入 “Hello”,客户端显示该消息,服务器等待客户端回复。
4. 客户端输入消息,同样会发送到服务器,双方可以持续交换消息,直到任一方输入 “quit” 命令。
#### 5. 处理多个客户端
为了处理多个客户端,可以使用线程。下面是一个简单的零件服务器和客户端应用程序示例。
##### 5.1 零件服务器
零件服务器使用 `HashMap` 来存储零件信息,零件名称作为键,价格作为 `Float` 对象存储。
```java
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
public class PartsServer {
private static final HashMap<String, Float> parts = new HashMap<>();
public PartsServer() {
System.out.println("Part Server Started");
initializeParts();
try {
ServerSocketChannel server
```
0
0
复制全文