帮我写一份下面代码的设计文档
/* Copyright(c) 2008-2024 ChengDu TP-LINK Technologies Co.Ltd.
*
* file common.c
* brief Provides common utility functions, including CRC32 checks, random data generation,
* timestamp printing, and more
* author Wang Junhang
* version 0.0.0
* date 2025-08-13
*
* history
*/
/************************************Include Files**********************************/
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <zlib.h>
/**
* brief Calculate the CRC32 checkpoint for a given data
* param[in] data Data pointers
* param[in] length Data length
* return uint32_t type CRC32 checks
*/
uint32_t calculate_crc32(const char *data, size_t length) {
return crc32(0, (const Bytef *)data, length);
}
/**
* brief Generate random data of specified length
* param[out] data Output data buffer
* param[in] length data length
*/
void generate_random_data(char *data, size_t length) {
for (size_t i = 0; i < length; i++) {
data[i] = rand() % 256;
}
}
/**
* brief Print the current timestamp
* note
*/
void print_timestamp() {
time_t now = time(NULL);
printf("[%ld] ", now);
}
/* Copyright(c) 2008-2024 ChengDu TP-LINK Technologies Co.Ltd.
*
* file main.c
* brief Application main portal file
* author Wang Junhang
* version 0.0.0
* date 2025-08-13
*
* history
*/
/************************************Include Files**********************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include "common.h"
/***********************************************************************************/
/* DEFINES */
/***********************************************************************************/
/***********************************************************************************/
/* TYPES */
/***********************************************************************************/
/***********************************************************************************/
/* EXTERN_PROTOTYPES */
extern void process_a();
extern void process_b();
/***********************************************************************************/
/***********************************************************************************/
/* LOCAL_PROTOTYPES */
/***********************************************************************************/
/***********************************************************************************/
/* VARIABLES */
/***********************************************************************************/
/***********************************************************************************/
/* LOCAL_FUNCTIONS */
/***********************************************************************************/
/***********************************************************************************/
/* PUBLIC_FUNCTIONS */
int main() {
srand(time(NULL));
pid_t pid = fork();
if (pid == 0) {
// 子进程作为接收方B
process_b();
exit(0);
} else if (pid > 0) {
// 父进程作为发送方A
sleep(1); // 确保B进程先启动
process_a();
// 等待B进程退出
kill(pid, SIGTERM);
waitpid(pid, NULL, 0);
} else {
perror("fork failed");
return 1;
}
return 0;
}
/* Copyright(c) 2008-2024 ChengDu TP-LINK Technologies Co.Ltd.
*
* file process_a.c
* brief Define the behavior of process A, which is responsible for sending IPC messages and
* receiving acknowledgments from B
* author Wang Junhang
* version 0.0.0
* date 2025-08-13
*
* history
*/
/************************************Include Files**********************************/
#include "common.h"
#include "socket_utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <time.h>
/***********************************************************************************/
/* DEFINES */
/***********************************************************************************/
/***********************************************************************************/
/* TYPES */
/***********************************************************************************/
/***********************************************************************************/
/* EXTERN_PROTOTYPES */
/***********************************************************************************/
/***********************************************************************************/
/* LOCAL_PROTOTYPES */
/***********************************************************************************/
/***********************************************************************************/
/* VARIABLES */
/***********************************************************************************/
/***********************************************************************************/
/* LOCAL_FUNCTIONS */
/***********************************************************************************/
/***********************************************************************************/
/* PUBLIC_FUNCTIONS */
/**
* brief The main function of process A
* details Process A is responsible for:
* 1. Initialize the local Unix domain socket
* 2. Construct IPC messages
* 3. Send a message to process B
* 4. Receive Acknowledgment (ACK) of Process B
* 5. Print sending and receiving statistics
*/
void process_a() {
struct sockaddr_un a_addr, b_addr;
int sock_fd = init_socket(SOCKET_A_PATH, &a_addr);
memset(&b_addr, 0, sizeof(b_addr));
b_addr.sun_family = AF_UNIX;
strncpy(b_addr.sun_path, SOCKET_B_PATH, sizeof(b_addr.sun_path) - 1);
size_t total_sent = 0, total_acked = 0;
int success_count = 0, fail_count = 0;
for (int i = 1; i < 4; i++) {
sleep(i); // 第i秒发送
ipc_message_t msg;
msg.timestamp = time(NULL);
msg.data_size = rand() % 500 + 100;
generate_random_data(msg.data, msg.data_size);
msg.checksum = calculate_crc32(msg.data, msg.data_size);
if (rand() % 4 == 0) msg.data[0] ^= 0xFF;
print_timestamp();
printf("A: 发送 %zu 字节数据给B\n", msg.data_size);
sendto(sock_fd, &msg, sizeof(msg), 0, (struct sockaddr*)&b_addr, sizeof(b_addr));
total_sent += msg.data_size;
ipc_ack_t ack;
recvfrom(sock_fd, &ack, sizeof(ack), 0, NULL, NULL);
print_timestamp();
if (ack.is_valid && ack.data_size == msg.data_size) {
success_count++;
total_acked += msg.data_size;
printf("A: B确认收到 %zu 字节(校验正确)\n", msg.data_size);
} else {
fail_count++;
printf("A: B确认收到 %zu 字节(校验失败)\n", msg.data_size);
}
}
printf("\n=== A进程统计 ===\n");
printf("发送总量: %zu 字节\n", total_sent);
printf("确认总量: %zu 字节\n", total_acked);
printf("成功率: %.2f%%\n", (success_count * 100.0) / (success_count + fail_count));
close(sock_fd);
unlink(SOCKET_A_PATH);
}
/***********************************************************************************/
/***********************************************************************************/
/* GLOBAL_FUNCTIONS */
/***********************************************************************************/
/* Copyright(c) 2008-2024 ChengDu TP-LINK Technologies Co.Ltd.
*
* file process_b.c
* brief Defines the behavior of process B, responsible for receiving IPC messages and sending
* ACKs
* author Wang Junhang
* version 0.0.0
* date 2025-08-13
*
* history
*/
/************************************Include Files**********************************/
#include "common.h"
#include "socket_utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
/***********************************************************************************/
/* DEFINES */
/***********************************************************************************/
/***********************************************************************************/
/* TYPES */
/***********************************************************************************/
/***********************************************************************************/
/* EXTERN_PROTOTYPES */
/***********************************************************************************/
/***********************************************************************************/
/* LOCAL_PROTOTYPES */
/***********************************************************************************/
/***********************************************************************************/
/* VARIABLES */
/***********************************************************************************/
/***********************************************************************************/
/* LOCAL_FUNCTIONS */
/***********************************************************************************/
/***********************************************************************************/
/* PUBLIC_FUNCTIONS */
/**
* brief Main function of process B
* details Process B is responsible for:
* 1. Initializing a local Unix domain socket
* 2. Receiving IPC messages from process A
* 3. Verifying the CRC32 checksum of received data
* 4. Sending an acknowledgment (ACK) back to A
* 5. Printing statistics about received data
*/
void process_b() {
struct sockaddr_un b_addr, a_addr;
int sock_fd = init_socket(SOCKET_B_PATH, &b_addr);
memset(&a_addr, 0, sizeof(a_addr));
a_addr.sun_family = AF_UNIX;
strncpy(a_addr.sun_path, SOCKET_A_PATH, sizeof(a_addr.sun_path) - 1);
size_t total_received = 0;
int success_count = 0, fail_count = 0;
while (1) {
ipc_message_t msg;
ssize_t len = recvfrom(sock_fd, &msg, sizeof(msg), 0, NULL, NULL);
if (len <= 0) break;
total_received += msg.data_size;
int is_valid = (calculate_crc32(msg.data, msg.data_size) == msg.checksum);
print_timestamp();
printf("B: 收到 %zu 字节数据 - ", msg.data_size);
printf(is_valid ? "校验正确\n" : "校验错误\n");
send_ack(sock_fd, &a_addr, is_valid, msg.data_size);
is_valid ? success_count++ : fail_count++;
}
printf("\n=== B进程统计 ===\n");
printf("接收总量: %zu 字节\n", total_received);
printf("成功率: %.2f%%\n", (success_count * 100.0) / (success_count + fail_count));
close(sock_fd);
unlink(SOCKET_B_PATH);
}
/***********************************************************************************/
/***********************************************************************************/
/* GLOBAL_FUNCTIONS */
/***********************************************************************************/
/* Copyright(c) 2008-2024 ChengDu TP-LINK Technologies Co.Ltd.
*
* file socket_utils.c
* brief Implementation of socket utility functions for Unix domain communication
* author Wang Junhang
* version 0.0.0
* date 2025-08-13
*
* history
*/
/************************************Include Files**********************************/
#include "socket_utils.h"
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
/***********************************************************************************/
/* DEFINES */
/***********************************************************************************/
/***********************************************************************************/
/* TYPES */
/***********************************************************************************/
/***********************************************************************************/
/* EXTERN_PROTOTYPES */
/***********************************************************************************/
/***********************************************************************************/
/* LOCAL_PROTOTYPES */
/***********************************************************************************/
/***********************************************************************************/
/* VARIABLES */
/***********************************************************************************/
/***********************************************************************************/
/* LOCAL_FUNCTIONS */
/***********************************************************************************/
/***********************************************************************************/
/* PUBLIC_FUNCTIONS */
/**
* brief Initialize a Unix domain datagram socket
* param[in] path Path to the Unix domain socket file
* param[out] addr Pointer to sockaddr_un structure to be initialized
* return File descriptor of the created socket
* details This function:
* 1. Creates a Unix domain datagram socket (SOCK_DGRAM)
* 2. Unlinks any existing socket file at the given path
* 3. Initializes the sockaddr_un structure
* 4. Binds the socket to the specified path
*/
int init_socket(const char *path, struct sockaddr_un *addr) {
int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
unlink(path);
memset(addr, 0, sizeof(*addr));
addr->sun_family = AF_UNIX;
strncpy(addr->sun_path, path, sizeof(addr->sun_path) - 1);
if (bind(fd, (struct sockaddr*)addr, sizeof(*addr))) {
perror("bind failed");
close(fd);
exit(EXIT_FAILURE);
}
return fd;
}
/**
* brief Send an acknowledgment message to the specified address
* param[in] sock_fd File descriptor of the socket
* param[in] addr Pointer to destination sockaddr_un address
* param[in] is_valid Validation result (1 = valid, 0 = invalid)
* param[in] data_size Size of the received data
* details Constructs an ipc_ack_t structure and sends it
* to the specified address using sendto().
*/
void send_ack(int sock_fd, const struct sockaddr_un *addr, int is_valid, size_t data_size) {
ipc_ack_t ack = { .is_valid = is_valid, .data_size = data_size };
sendto(sock_fd, &ack, sizeof(ack), 0, (struct sockaddr*)addr, sizeof(*addr));
}
/***********************************************************************************/
/***********************************************************************************/
/* GLOBAL_FUNCTIONS */
/***********************************************************************************/
/* Copyright(c) 2008-2024 ChengDu TP-LINK Technologies Co.Ltd.
*
* file socket_utils.c
* brief Implementation of socket utility functions for Unix domain communication
* author Wang Junhang
* version 0.0.0
* date 2025-08-13
*
* history
*/
/************************************Include Files**********************************/
#include "socket_utils.h"
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
/***********************************************************************************/
/* DEFINES */
/***********************************************************************************/
/***********************************************************************************/
/* TYPES */
/***********************************************************************************/
/***********************************************************************************/
/* EXTERN_PROTOTYPES */
/***********************************************************************************/
/***********************************************************************************/
/* LOCAL_PROTOTYPES */
/***********************************************************************************/
/***********************************************************************************/
/* VARIABLES */
/***********************************************************************************/
/***********************************************************************************/
/* LOCAL_FUNCTIONS */
/***********************************************************************************/
/***********************************************************************************/
/* PUBLIC_FUNCTIONS */
/**
* brief Initialize a Unix domain datagram socket
* param[in] path Path to the Unix domain socket file
* param[out] addr Pointer to sockaddr_un structure to be initialized
* return File descriptor of the created socket
* details This function:
* 1. Creates a Unix domain datagram socket (SOCK_DGRAM)
* 2. Unlinks any existing socket file at the given path
* 3. Initializes the sockaddr_un structure
* 4. Binds the socket to the specified path
*/
int init_socket(const char *path, struct sockaddr_un *addr) {
int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
unlink(path);
memset(addr, 0, sizeof(*addr));
addr->sun_family = AF_UNIX;
strncpy(addr->sun_path, path, sizeof(addr->sun_path) - 1);
if (bind(fd, (struct sockaddr*)addr, sizeof(*addr))) {
perror("bind failed");
close(fd);
exit(EXIT_FAILURE);
}
return fd;
}
/**
* brief Send an acknowledgment message to the specified address
* param[in] sock_fd File descriptor of the socket
* param[in] addr Pointer to destination sockaddr_un address
* param[in] is_valid Validation result (1 = valid, 0 = invalid)
* param[in] data_size Size of the received data
* details Constructs an ipc_ack_t structure and sends it
* to the specified address using sendto().
*/
void send_ack(int sock_fd, const struct sockaddr_un *addr, int is_valid, size_t data_size) {
ipc_ack_t ack = { .is_valid = is_valid, .data_size = data_size };
sendto(sock_fd, &ack, sizeof(ack), 0, (struct sockaddr*)addr, sizeof(*addr));
}
/***********************************************************************************/
/***********************************************************************************/
/* GLOBAL_FUNCTIONS */
/***********************************************************************************/
最新发布