XNSim/XNServices/XNUDPService/XNUDPService.cpp

205 lines
5.4 KiB
C++
Raw Normal View History

2025-04-28 12:25:20 +08:00
#include "XNUDPService.h"
#include "XNUDPService_p.h"
#include <XNCore/XNServiceManager.h>
#include <XNCore/XNDDSManager.h>
2025-05-22 16:22:48 +08:00
#include <fstream>
#include <sstream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <XNCore/XNByteArray.h>
XN_SERVICE_INITIALIZE(XNUDPService)
XNUDPService::XNUDPService() : XNServiceObject(new XNUDPServicePrivate())
2025-04-28 12:25:20 +08:00
{
}
XNUDPService::~XNUDPService()
{
2025-05-22 16:22:48 +08:00
T_D();
if (d->udpSocket >= 0) {
close(d->udpSocket);
d->udpSocket = -1;
}
};
2025-04-28 12:25:20 +08:00
2025-05-22 16:22:48 +08:00
XNUDPService::XNUDPService(PrivateType *p) : XNServiceObject(p)
2025-04-28 12:25:20 +08:00
{
}
2025-05-22 16:22:48 +08:00
void XNUDPService::Initialize()
2025-04-28 12:25:20 +08:00
{
2025-05-22 16:22:48 +08:00
XNServiceObject::Initialize();
T_D();
2025-04-28 12:25:20 +08:00
// 读取配置文件
2025-05-22 16:22:48 +08:00
std::ifstream file(GetXmlPath());
if (!file.is_open()) {
LOG_WARNING("无法打开配置文件:%s", GetXmlPath().c_str());
2025-04-28 12:25:20 +08:00
return;
}
2025-05-22 16:22:48 +08:00
std::stringstream buffer;
buffer << file.rdbuf();
std::string content = buffer.str();
2025-04-28 12:25:20 +08:00
file.close();
2025-05-22 16:22:48 +08:00
// 简单的XML解析
size_t udpPos = content.find("<UDP>");
if (udpPos != std::string::npos) {
size_t localPortPos = content.find("<LocalPort>", udpPos);
size_t targetHostPos = content.find("<TargetHost>", udpPos);
size_t targetPortPos = content.find("<TargetPort>", udpPos);
if (localPortPos != std::string::npos) {
size_t endPos = content.find("</LocalPort>", localPortPos);
d->localPort = std::stoi(content.substr(localPortPos + 11, endPos - localPortPos - 11));
}
if (targetHostPos != std::string::npos) {
size_t endPos = content.find("</TargetHost>", targetHostPos);
d->targetHost = content.substr(targetHostPos + 12, endPos - targetHostPos - 12);
}
if (targetPortPos != std::string::npos) {
size_t endPos = content.find("</TargetPort>", targetPortPos);
d->targetPort =
std::stoi(content.substr(targetPortPos + 12, endPos - targetPortPos - 12));
}
2025-04-28 12:25:20 +08:00
} else {
LOG_WARNING("未找到UDP配置, 使用默认值");
2025-04-28 12:25:20 +08:00
d->localPort = 12345;
d->targetHost = "127.0.0.1";
d->targetPort = 54321;
}
}
2025-05-22 16:22:48 +08:00
void XNUDPService::PrepareForExecute()
2025-04-28 12:25:20 +08:00
{
2025-05-22 16:22:48 +08:00
XNServiceObject::PrepareForExecute();
T_D();
2025-04-28 12:25:20 +08:00
// 初始化UDP socket
2025-05-22 16:22:48 +08:00
d->udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (d->udpSocket < 0) {
LOG_WARNING("无法创建UDP socket");
2025-05-22 16:22:48 +08:00
return;
}
// 设置非阻塞模式
int flags = fcntl(d->udpSocket, F_GETFL, 0);
fcntl(d->udpSocket, F_SETFL, flags | O_NONBLOCK);
2025-04-28 12:25:20 +08:00
// 绑定本地端口
2025-05-22 16:22:48 +08:00
struct sockaddr_in localAddr;
memset(&localAddr, 0, sizeof(localAddr));
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = INADDR_ANY;
localAddr.sin_port = htons(d->localPort);
if (bind(d->udpSocket, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) {
LOG_WARNING("UDP socket 绑定失败, 端口:%d", d->localPort);
2025-05-22 16:22:48 +08:00
close(d->udpSocket);
d->udpSocket = -1;
2025-04-28 12:25:20 +08:00
return;
}
RegisterRTEventHandler("SendUDPData",
std::bind(&XNUDPService::SendData, this, std::placeholders::_1));
}
void XNUDPService::HandleIncomingData()
{
2025-05-22 16:22:48 +08:00
T_D();
if (d->udpSocket < 0)
return;
char buffer[65536];
struct sockaddr_in senderAddr;
socklen_t senderLen = sizeof(senderAddr);
2025-04-28 12:25:20 +08:00
2025-05-22 16:22:48 +08:00
while (true) {
ssize_t bytesRead = recvfrom(d->udpSocket, buffer, sizeof(buffer), 0,
(struct sockaddr *)&senderAddr, &senderLen);
2025-04-28 12:25:20 +08:00
2025-05-22 16:22:48 +08:00
if (bytesRead <= 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
break; // 没有更多数据
}
LOG_WARNING("读取UDP socket失败");
2025-05-22 16:22:48 +08:00
break;
}
if (bytesRead <= 8) {
LOG_WARNING("UDP 数据包小于8字节");
2025-04-28 16:41:21 +08:00
continue;
}
// 将数据转换为XNByteArray
XNByteArray datagram;
datagram.resize(bytesRead);
memcpy(datagram.data(), buffer, bytesRead);
if (datagram[0] != 0xa6) {
LOG_WARNING("UDP 数据包头无效, 头:%1", datagram[0]);
continue;
}
2025-05-22 16:22:48 +08:00
if (datagram[5] != 0x00) {
LOG_WARNING("UDP 数据包传输方向错误, 方向:%1", datagram[5]);
2025-04-28 16:41:21 +08:00
continue;
}
uint16_t dataSize = ((uint16_t)datagram[6] << 8) | (uint16_t)datagram[7];
if (dataSize != bytesRead) {
LOG_WARNING("UDP 数据包大小无效, 大小:%d, 实际大小:%zd", dataSize, bytesRead - 8);
2025-04-28 12:25:20 +08:00
continue;
}
2025-04-28 16:41:21 +08:00
uint8_t planeHeader = datagram[1];
uint8_t ataHeader = datagram[2];
uint8_t modelHeader = datagram[3];
uint8_t structHeader = datagram[4];
if (planeHeader == 0xc0) { //C909数据
if (ataHeader == 0x04) { //ATA04章节数据
if (modelHeader == 0x00 && structHeader == 0x00) { //气动输入数据
TriggerRTEvent("C909::ATA04::AeroInput", datagram);
continue;
} else if (modelHeader == 0x01 && structHeader == 0x00) { //地操输入数据
TriggerRTEvent("C909::ATA04::GhInput", datagram);
continue;
} else if (modelHeader == 0x02 && structHeader == 0x00) { //质量输入数据
TriggerRTEvent("C909::ATA04::WbInput", datagram);
continue;
}
2025-04-28 12:25:20 +08:00
}
} else {
TriggerRTEvent("ReceiveUDPData", datagram);
2025-04-28 12:25:20 +08:00
}
}
}
2025-05-22 16:22:48 +08:00
void XNUDPService::SendData(const std::any &data)
2025-04-28 12:25:20 +08:00
{
2025-05-22 16:22:48 +08:00
T_D();
if (d->udpSocket < 0) {
2025-04-28 12:25:20 +08:00
LOG_WARNING("UDP socket not initialized");
return;
}
2025-05-22 16:22:48 +08:00
struct sockaddr_in targetAddr;
memset(&targetAddr, 0, sizeof(targetAddr));
targetAddr.sin_family = AF_INET;
targetAddr.sin_port = htons(d->targetPort);
inet_pton(AF_INET, d->targetHost.c_str(), &targetAddr.sin_addr);
XNByteArray packet = std::any_cast<XNByteArray>(data);
ssize_t bytesSent = sendto(d->udpSocket, packet.data(), packet.size(), 0,
(struct sockaddr *)&targetAddr, sizeof(targetAddr));
2025-04-28 12:25:20 +08:00
2025-05-22 16:22:48 +08:00
if (bytesSent < 0) {
LOG_WARNING("Failed to send UDP datagram: %s", strerror(errno));
2025-04-28 12:25:20 +08:00
}
}