217 lines
6.2 KiB
Markdown
217 lines
6.2 KiB
Markdown
# UDP多播发送功能说明
|
||
|
||
## 概述
|
||
|
||
本功能实现了UDP多播发送逻辑,对应C++代码`TLogServer.cpp`中的发送广播机制。作为独立功能,不依赖Spring框架,可以直接使用。
|
||
|
||
## 功能对应关系
|
||
|
||
### C++代码对应关系
|
||
|
||
| C++代码 | Java实现 | 说明 |
|
||
|---------|---------|------|
|
||
| `m_SendCtrl.Start(m_iSendPort, m_IP.c_str())` | `MulticastSender.initialize()` | 启动UDP多播发送 |
|
||
| `m_SendCtrl.AddChannel(m_SendGrpIP.c_str(), m_iSendPort)` | `MulticastSender`构造函数配置 | 配置发送通道 |
|
||
| `m_SendCtrl.Send(item)` | `MulticastSender.send(item)` | 发送COP_ITEM数据 |
|
||
| `item->GetMessage()` | `COPMessageBuilder.buildMessage(item)` | 构建COP协议消息 |
|
||
|
||
## 核心组件
|
||
|
||
### 1. MulticastSender
|
||
|
||
UDP多播发送器,负责:
|
||
- 创建并配置UDP多播Socket
|
||
- 发送COP协议数据
|
||
- 管理发送状态和监听器
|
||
|
||
**位置**: `com.afe.dc.tranlog.service.multicast.MulticastSender`
|
||
|
||
**主要方法**:
|
||
- `initialize()`: 初始化发送器
|
||
- `send(COPItem item)`: 发送COPItem数据
|
||
- `sendRaw(byte[] data)`: 发送原始字节数据
|
||
- `close()`: 关闭发送器
|
||
- `addListener(SendListener listener)`: 添加发送监听器
|
||
|
||
### 2. COPMessageBuilder
|
||
|
||
COP协议消息构建器,负责将`COPItem`对象转换为字节数组(COP协议格式)。
|
||
|
||
**位置**: `com.afe.dc.tranlog.service.multicast.COPMessageBuilder`
|
||
|
||
**主要方法**:
|
||
- `buildMessage(COPItem item)`: 构建COP协议消息
|
||
|
||
## 使用示例
|
||
|
||
### 基本使用
|
||
|
||
```java
|
||
// 1. 创建发送配置
|
||
MulticastSender.Config config = new MulticastSender.Config(
|
||
5001, // 发送端口
|
||
"225.6.7.9" // 多播组IP
|
||
);
|
||
config.setLocalIp("0.0.0.0") // 本地IP(可选)
|
||
.setTtl(1) // TTL值(可选,默认1)
|
||
.setLoopbackDisabled(true); // 禁用回环(可选,默认true)
|
||
|
||
// 2. 创建发送器
|
||
MulticastSender sender = new MulticastSender(config);
|
||
|
||
// 3. 初始化
|
||
if (!sender.initialize()) {
|
||
System.err.println("初始化失败");
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// 4. 创建COPItem数据
|
||
COPItem item = COPItem.builder()
|
||
.itemNo(12345L)
|
||
.msgType(COPItem.MsgType.MGT_UPDATE)
|
||
.build();
|
||
|
||
// 添加FID字段
|
||
item.addField(COPItem.FID.FID_TRAN_LOG, "交易数据");
|
||
item.addField(COPItem.FID.FID_ASK, 100.5f);
|
||
item.addField(COPItem.FID.FID_BID, 100.3f);
|
||
|
||
// 5. 发送数据
|
||
boolean success = sender.send(item);
|
||
|
||
} finally {
|
||
// 6. 关闭发送器
|
||
sender.close();
|
||
}
|
||
```
|
||
|
||
### 使用发送监听器
|
||
|
||
```java
|
||
// 添加发送监听器
|
||
sender.addListener(new MulticastSender.SendListener() {
|
||
@Override
|
||
public void onSendSuccess(COPItem item, int bytesSent) {
|
||
System.out.println("发送成功 - itemNo: " + item.getItemNo()
|
||
+ ", 大小: " + bytesSent + " 字节");
|
||
}
|
||
|
||
@Override
|
||
public void onSendError(COPItem item, Exception error) {
|
||
System.err.println("发送失败 - itemNo: " + item.getItemNo()
|
||
+ ", 错误: " + error.getMessage());
|
||
}
|
||
});
|
||
```
|
||
|
||
### 发送原始字节数据
|
||
|
||
```java
|
||
byte[] rawData = new byte[]{0x01, 0x02, 0x03, 0x04};
|
||
sender.sendRaw(rawData);
|
||
```
|
||
|
||
## 配置说明
|
||
|
||
### MulticastSender.Config
|
||
|
||
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
||
|------|------|------|--------|------|
|
||
| sendPort | int | 是 | - | 发送端口 |
|
||
| groupIp | String | 是 | - | 多播组IP地址 |
|
||
| localIp | String | 否 | "0.0.0.0" | 本地网络接口IP地址 |
|
||
| ttl | int | 否 | 1 | TTL值(Time To Live) |
|
||
| loopbackDisabled | boolean | 否 | true | 是否禁用回环 |
|
||
|
||
### 配置方法
|
||
|
||
```java
|
||
MulticastSender.Config config = new MulticastSender.Config(5001, "225.6.7.9")
|
||
.setLocalIp("192.168.1.100") // 链式调用设置本地IP
|
||
.setTtl(2) // 设置TTL
|
||
.setLoopbackDisabled(false); // 允许回环
|
||
```
|
||
|
||
## COP协议格式
|
||
|
||
当前实现的COP协议格式:
|
||
|
||
```
|
||
消息头(16字节):
|
||
- 消息类型(1字节)
|
||
- ItemNo(4字节,小端序)
|
||
- 其他头部信息(11字节,当前用0填充)
|
||
|
||
FID字段(每个字段):
|
||
- FID编号(2字节)
|
||
- 数据类型(1字节)
|
||
- 数据长度(2字节)
|
||
- 数据内容(变长)
|
||
```
|
||
|
||
### 支持的数据类型
|
||
|
||
| 数据类型 | 标识 | Java类型 | 大小 |
|
||
|---------|------|----------|------|
|
||
| CHAR | 0x01 | Byte, Character | 1字节 |
|
||
| SHORT | 0x02 | Short | 2字节 |
|
||
| INT | 0x04 | Integer | 4字节 |
|
||
| LONG | 0x08 | Long | 8字节 |
|
||
| FLOAT | 0x10 | Float | 4字节 |
|
||
| DOUBLE | 0x20 | Double | 8字节 |
|
||
| STRING | 0x40 | String | 变长 |
|
||
| BYTE_ARRAY | 0x80 | byte[] | 变长 |
|
||
|
||
## 注意事项
|
||
|
||
1. **独立功能**: 本功能不依赖Spring框架,可以在任何Java应用中使用。
|
||
|
||
2. **线程安全**: `MulticastSender`不是线程安全的,如果需要在多线程环境中使用,需要外部同步。
|
||
|
||
3. **资源管理**: 使用完毕后务必调用`close()`方法释放资源。
|
||
|
||
4. **网络权限**: 在某些操作系统上,发送UDP多播数据可能需要特殊权限。
|
||
|
||
5. **防火墙**: 确保防火墙允许UDP数据包通过配置的端口。
|
||
|
||
6. **TTL值**: TTL值决定了数据包可以经过的路由器数量,通常设置为1(本地网络)或更大的值(跨网络)。
|
||
|
||
7. **回环**: 如果`loopbackDisabled`为`true`,发送的数据不会回环到本地接收端,适合生产环境。
|
||
|
||
## 故障排查
|
||
|
||
### 初始化失败
|
||
|
||
1. 检查多播组IP地址是否有效(必须是224.0.0.0到239.255.255.255之间)
|
||
2. 检查端口是否被占用
|
||
3. 检查网络接口是否正确
|
||
4. 查看日志中的详细错误信息
|
||
|
||
### 发送失败
|
||
|
||
1. 检查网络连接
|
||
2. 检查防火墙设置
|
||
3. 检查多播组地址和端口是否正确
|
||
4. 查看日志中的详细错误信息
|
||
|
||
### 数据格式问题
|
||
|
||
1. 检查COP协议格式是否与接收端一致
|
||
2. 检查数据类型是否正确
|
||
3. 查看`COPMessageBuilder`的构建逻辑
|
||
|
||
## 扩展
|
||
|
||
如果需要扩展功能,可以:
|
||
|
||
1. **自定义协议格式**: 修改`COPMessageBuilder`以支持不同的协议格式
|
||
2. **批量发送**: 添加批量发送方法
|
||
3. **异步发送**: 添加异步发送支持
|
||
4. **发送统计**: 添加发送统计和监控功能
|
||
5. **重试机制**: 添加发送失败重试机制
|
||
|
||
## 完整示例
|
||
|
||
参考 `MulticastSenderExample.java` 文件中的完整示例代码。
|