-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
330 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <arpa/inet.h> | ||
#include <sys/socket.h> | ||
#include <unistd.h> | ||
#include "ldou.h" | ||
|
||
int main() { | ||
int sockfd; | ||
struct sockaddr_in servaddr, cliaddr; | ||
|
||
// 创建 UDP socket | ||
sockfd = socket(AF_INET, SOCK_DGRAM, 0); | ||
if (sockfd < 0) { | ||
perror("Socket creation failed"); | ||
return -1; | ||
} | ||
|
||
memset(&servaddr, 0, sizeof(servaddr)); | ||
servaddr.sin_family = AF_INET; | ||
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); | ||
servaddr.sin_port = htons(12345); | ||
|
||
// 构造 LDOU 数据包 | ||
ldou_packet_t packet; | ||
packet.flag = 0x1234; | ||
packet.len = 5; | ||
packet.addr = 1; | ||
packet.cmd = 2; | ||
packet.data[0] = 3; | ||
packet.data[1] = 4; | ||
packet.sum = ldou_calculate_checksum(&packet); | ||
|
||
// 构造发送缓冲区 | ||
uint8_t buffer[128] = {0}; | ||
buffer[0] = (uint8_t)(packet.flag >> 8); | ||
buffer[1] = (uint8_t)(packet.flag & 0xFF); | ||
buffer[2] = packet.len; | ||
buffer[3] = packet.addr; | ||
buffer[4] = packet.cmd; | ||
memcpy(&buffer[5], packet.data, packet.len - 3); | ||
buffer[2 + packet.len] = packet.sum; | ||
|
||
// 发送数据包 | ||
ssize_t sent = sendto(sockfd, buffer, 3 + packet.len, 0, (const struct sockaddr *)&servaddr, sizeof(servaddr)); | ||
if (sent < 0) { | ||
perror("Failed to send data"); | ||
close(sockfd); | ||
return -1; | ||
} | ||
|
||
printf("Packet sent successfully\n"); | ||
|
||
// 接收响应 | ||
socklen_t len = sizeof(cliaddr); | ||
size_t n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&cliaddr, &len); | ||
if (n < 0) { | ||
perror("Failed to receive data"); | ||
close(sockfd); | ||
return -1; | ||
} | ||
|
||
printf("Received response: "); | ||
|
||
for (ssize_t i = 0; i < n; i++) | ||
{ | ||
printf("%02X ", buffer[i]); | ||
} | ||
printf("\n"); | ||
|
||
close(sockfd); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
#include "ldou.h" | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <arpa/inet.h> | ||
#include <sys/socket.h> | ||
#include <unistd.h> | ||
|
||
static int socket_fd = -1; | ||
static struct sockaddr_in remote_addr; | ||
|
||
ldou_handler_t command_handler = NULL; | ||
|
||
/** | ||
* @brief 计算校验和 | ||
*/ | ||
uint8_t ldou_calculate_checksum(const ldou_packet_t *packet) | ||
{ | ||
uint8_t sum = 0; | ||
|
||
sum += (uint8_t)(packet->flag >> 8); | ||
sum += (uint8_t)(packet->flag & 0xFF); | ||
sum += packet->len; | ||
sum += packet->addr; | ||
sum += packet->cmd; | ||
|
||
for (uint8_t i = 0; i < packet->len - 3; i++) | ||
{ | ||
sum += packet->data[i]; | ||
} | ||
|
||
return sum; | ||
} | ||
|
||
/** | ||
* @brief 初始化 LDOU 协议 | ||
*/ | ||
int ldou_init(const char *bind_ip, uint16_t port) | ||
{ | ||
if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) | ||
{ | ||
perror("Socket creation failed"); | ||
return -1; | ||
} | ||
|
||
struct sockaddr_in local_addr = {0}; | ||
local_addr.sin_family = AF_INET; | ||
local_addr.sin_addr.s_addr = inet_addr(bind_ip); | ||
local_addr.sin_port = htons(port); | ||
|
||
if (bind(socket_fd, (const struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) | ||
{ | ||
perror("Socket bind failed"); | ||
return -1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/** | ||
* @brief 接收数据并解析为 LDOU 数据包 | ||
*/ | ||
int ldou_receive(ldou_packet_t *packet) | ||
{ | ||
uint8_t buffer[128] = {0}; | ||
socklen_t addr_len = sizeof(remote_addr); | ||
|
||
ssize_t received = recvfrom(socket_fd, buffer, sizeof(buffer), 0, (struct sockaddr *)&remote_addr, &addr_len); | ||
|
||
if (received <= 0) | ||
{ | ||
perror("Failed to receive data"); | ||
return -1; | ||
} | ||
|
||
packet->flag = (uint16_t)buffer[0] << 8 | buffer[1]; | ||
packet->len = buffer[2]; | ||
packet->addr = buffer[3]; | ||
packet->cmd = buffer[4]; | ||
|
||
size_t data_size = packet->len - 3; | ||
|
||
if (data_size > LDOU_MAX_DATA_SIZE) | ||
{ | ||
return -2; // 数据过长 | ||
} | ||
|
||
memcpy(packet->data, &buffer[5], data_size); | ||
packet->sum = buffer[2 + packet->len]; | ||
|
||
uint8_t calculated_sum = ldou_calculate_checksum(packet); | ||
|
||
return (calculated_sum == packet->sum) ? 0 : -3; // 校验和错误 | ||
} | ||
|
||
/** | ||
* @brief 发送 LDOU 数据包 | ||
*/ | ||
int ldou_send(const ldou_packet_t *packet) | ||
{ | ||
uint8_t buffer[128] = {0}; | ||
|
||
buffer[0] = (uint8_t)(packet->flag >> 8); | ||
buffer[1] = (uint8_t)(packet->flag & 0xFF); | ||
buffer[2] = packet->len; | ||
buffer[3] = packet->addr; | ||
buffer[4] = packet->cmd; | ||
|
||
memcpy(&buffer[5], packet->data, packet->len - 3); | ||
|
||
buffer[packet->len + 2] = packet->sum; | ||
|
||
ssize_t sent = sendto(socket_fd, buffer, packet->len + 3, 0, (struct sockaddr *)&remote_addr, sizeof(remote_addr)); | ||
|
||
if (send <= 0) | ||
{ | ||
perror("Failed to send data"); | ||
return -1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/** | ||
* @brief 注册命令处理回调函数 | ||
*/ | ||
void ldou_register_handler(ldou_handler_t handler) | ||
{ | ||
command_handler = handler; | ||
} | ||
|
||
/** | ||
* @brief 清理资源 | ||
*/ | ||
void ldou_cleanup() | ||
{ | ||
if (socket_fd >= 0) | ||
{ | ||
close(socket_fd); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#ifndef LDOU_H | ||
#define LDOU_H | ||
|
||
#include <stdint.h> | ||
#include <stddef.h> | ||
|
||
#define LDOU_FLAG1 0x7E7E | ||
#define LDOU_FLAG2 0xE7E7 | ||
#define LDOU_BROADCAST_ADDR 0xFF | ||
#define LDOU_MAX_DATA_SIZE 64 | ||
|
||
/** | ||
* @brief LDOU 数据包结构 | ||
*/ | ||
typedef struct { | ||
uint16_t flag; /// < 报文标志位 | ||
uint8_t len; /// < 报文长度(含地址、命令、数据和校验和) | ||
uint8_t addr; /// < 目标地址 | ||
uint8_t cmd; /// < 命令字 | ||
uint8_t data[LDOU_MAX_DATA_SIZE]; /// 数据部分 | ||
uint8_t sum; /// 校验和 | ||
} ldou_packet_t; | ||
|
||
typedef void (*ldou_handler_t)(const ldou_packet_t *request, ldou_packet_t *response); | ||
|
||
extern ldou_handler_t command_handler; | ||
|
||
extern uint8_t ldou_calculate_checksum(const ldou_packet_t *packet); | ||
|
||
// 初始化接口 | ||
extern int ldou_init(const char *bind_ip, uint16_t port); | ||
|
||
// 接收数据接口 | ||
extern int ldou_receive(ldou_packet_t *packet); | ||
|
||
// 发送数据接口 | ||
extern int ldou_send(const ldou_packet_t *packet); | ||
|
||
// 注册命令处理回调接口 | ||
void ldou_register_handler(ldou_handler_t handler); | ||
|
||
// 清理资源接口 | ||
void ldou_cleanup(); | ||
|
||
|
||
|
||
#endif // LDOU_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
#include "ldou.h" | ||
|
||
void example_command_handler(const ldou_packet_t *request, ldou_packet_t *response) | ||
{ | ||
printf("Received command: 0x%02X\n", request->cmd); | ||
printf("Data length: %d\n", request->len - 3); | ||
|
||
for (int i = 0; i < request-> len - 3; i++) | ||
{ | ||
printf("Data[%d]: 0x%02X\n", i, request->data[i]); | ||
} | ||
|
||
// 填充应答包 | ||
response->flag = LDOU_FLAG2; | ||
response->len = request->addr; | ||
response->cmd = request->cmd; | ||
response->len = 4; | ||
response->data[0] = 0x00; | ||
response->sum = ldou_calculate_checksum(response); | ||
} | ||
|
||
int main() | ||
{ | ||
const char *bind_ip = "0.0.0.0"; | ||
uint16_t port = 12345; | ||
|
||
if (ldou_init(bind_ip, port) != 0) | ||
{ | ||
printf("Failed to initialize LDOU protocol.\n"); | ||
return -1; | ||
} | ||
|
||
printf("LDOU protocol initialized. Waiting for commands on %s:%d...\n", bind_ip, port); | ||
|
||
// 注册命令处理函数 | ||
ldou_register_handler(example_command_handler); | ||
|
||
while (1) | ||
{ | ||
ldou_packet_t request; | ||
ldou_packet_t response; | ||
|
||
int result = ldou_receive(&request); | ||
|
||
if (result == 0) | ||
{ | ||
printf("Packet received successfully.\n"); | ||
|
||
// 调用命令处理函数 | ||
command_handler(&request, &response); | ||
|
||
if (ldou_send(&response)) | ||
{ | ||
printf("Response sent successfully.\n"); | ||
} | ||
else | ||
{ | ||
printf("Failed to send response.\n"); | ||
} | ||
} | ||
else | ||
{ | ||
printf("Error receiving packet: %d\n", result); | ||
} | ||
} | ||
|
||
ldou_cleanup(); | ||
|
||
return 0; | ||
} |
File renamed without changes.
File renamed without changes.