va_start&strcat&strstr

本文详细解释了C语言中va_list、va_start和va_end宏的使用方法,并通过实例展示了如何利用这些宏来处理可变数量的参数。此外,还介绍了strstr和strcat等字符串操作函数的基本用法。

1.va_start&va_arg& va_end  

int   sprintf   (char   *   szBuffer,   const   char   *   szFormat,   ...)  
  {  
            int           iReturn   ;  
            va_list   pArgs   ;  
   
            va_start   (pArgs,   szFormat)   ;//??  
            iReturn   =   vsprintf   (szBuffer,   szFormat,   pArgs)   ;  
            va_end   (pArgs)   ;  
   
            return   iReturn   ;  
  }  
  va_list,va_start,va_end为何意?  
      注:vsprintf的前俩个参数与sprintf相同:保存结果的字符缓冲区和  
  格式字符串,第三个:指向格式化参数数组的指针。

-----------------------------------------------------------------

取得可变参数的,可以参考一下msdn上的这个例子  
  Example  
   
  /*   VA.C:   The   program   below   illustrates   passing   a   variable  
    *   number   of   arguments   using   the   following   macros:  
    *             va_start                         va_arg                             va_end  
    *             va_list                           va_dcl   (UNIX   only)  
    */  
   
  #include   <stdio.h>  
  #define   ANSI                         /*   Comment   out   for   UNIX   version           */  
  #ifdef   ANSI                           /*   ANSI   compatible   version                     */  
  #include   <stdarg.h>  
  int   average(   int   first,   ...   );  
  #else                                       /*   UNIX   compatible   version                     */  
  #include   <varargs.h>  
  int   average(   va_list   );  
  #endif  
   
  void   main(   void   )  
  {  
        /*   Call   with   3   integers   (-1   is   used   as   terminator).   */  
        printf(   "Average   is:   %d/n",   average(   2,   3,   4,   -1   )   );  
   
        /*   Call   with   4   integers.   */  
        printf(   "Average   is:   %d/n",   average(   5,   7,   9,   11,   -1   )   );  
   
        /*   Call   with   just   -1   terminator.   */  
        printf(   "Average   is:   %d/n",   average(   -1   )   );  
  }  
   
  /*   Returns   the   average   of   a   variable   list   of   integers.   */  
  #ifdef   ANSI                           /*   ANSI   compatible   version         */  
  int   average(   int   first,   ...   )  
  {  
        int   count   =   0,   sum   =   0,   i   =   first;  
        va_list   marker;  
   
        va_start(   marker,   first   );           /*   Initialize   variable   arguments.   */  
        while(   i   !=   -1   )  
        {  
              sum   +=   i;  
              count++;  
              i   =   va_arg(   marker,   int);  
        }  
        va_end(   marker   );                             /*   Reset   variable   arguments.             */  
        return(   sum   ?   (sum   /   count)   :   0   );  
  }  
  #else               /*   UNIX   compatible   version   must   use   old-style   definition.     */  
  int   average(   va_alist   )  
  va_dcl  
  {  
        int   i,   count,   sum;  
        va_list   marker;  
   
        va_start(   marker   );                         /*   Initialize   variable   arguments.   */  
        for(   sum   =   count   =   0;   (i   =   va_arg(   marker,   int))   !=   -1;   count++   )  
              sum   +=   i;  
        va_end(   marker   );                             /*   Reset   variable   arguments.             */  
        return(   sum   ?   (sum   /   count)   :   0   );  
  }  
  #endif  
   
   
  Output  
   
  Average   is:   3  
  Average   is:   8  
  Average   is:   0  
   
   
  更多的看看msdn 

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

2.strstr(a,b)求子字符串b在a中出现的位置;

strcat(a,b)将字符串b拼接到字符串a的后面;

#include <stdint.h> #include <string.h> #include <math.h> #include "stm32h7xx_it.h" // 寄存器地址定义 (STM32H743VIT6) #define RCC_BASE1 0x58024400UL #define GPIOE_BASE1 0x58021000UL #define USART8_BASE 0x40007C00UL #define NVIC_BASE1 0xE000E100UL // RCC寄存器 #define RCC_AHB4ENR (*(volatile uint32_t *)(RCC_BASE1 + 0xE0)) #define RCC_APB2ENR (*(volatile uint32_t *)(RCC_BASE1 + 0x60)) // GPIO寄存器 #define GPIOE_MODER (*(volatile uint32_t *)(GPIOE_BASE1 + 0x00)) #define GPIOE_OTYPER (*(volatile uint32_t *)(GPIOE_BASE1 + 0x04)) #define GPIOE_OSPEEDR (*(volatile uint32_t *)(GPIOE_BASE1 + 0x08)) #define GPIOE_PUPDR (*(volatile uint32_t *)(GPIOE_BASE1 + 0x0C)) #define GPIOE_ODR (*(volatile uint32_t *)(GPIOE_BASE1 + 0x14)) #define GPIOE_AFRL (*(volatile uint32_t *)(GPIOE_BASE1 + 0x20)) // USART寄存器 #define USART8_CR1 (*(volatile uint32_t *)(USART8_BASE + 0x00)) #define USART8_CR2 (*(volatile uint32_t *)(USART8_BASE + 0x04)) #define USART8_CR3 (*(volatile uint32_t *)(USART8_BASE + 0x08)) #define USART8_BRR (*(volatile uint32_t *)(USART8_BASE + 0x0C)) #define USART8_ISR (*(volatile uint32_t *)(USART8_BASE + 0x1C)) #define USART8_RDR (*(volatile uint32_t *)(USART8_BASE + 0x24)) #define USART8_TDR (*(volatile uint32_t *)(USART8_BASE + 0x28)) // NVIC寄存器 #define NVIC_ISER1 (*(volatile uint32_t *)(NVIC_BASE1 + 0x04)) #define NVIC_IPR8 (*(volatile uint32_t *)(NVIC_BASE1 + 0x320)) // 时钟和引脚定义 #define USART8_CLK_EN() (RCC_APB2ENR |= (1 << 18)) #define GPIOE_CLK_EN() (RCC_AHB4ENR |= (1 << 4)) // 传感器数据结构 typedef struct { uint32_t id; float value; } SensorData; // 全局变量 volatile uint32_t systick_counter = 0; const char *MQTT_SERVER = "tcp://118.190.157.186:61613"; // MQTT代理地址 const char *MQTT_TOPIC = "A/XZRS/0/1705001"; // MQTT主题 const char *MQTT_CLIENT_ID = "8c1e7aa1-6307-4c88-b48a-828e1f987544"; // 客户端ID const char *MQTT_USERNAME = "your_username"; // 云平台用户名 const char *MQTT_PASSWORD = "your_password"; // 云平台密码 // 系统时钟配置 void SystemClock_Config(void) { // 实际项目中需要配置PLL等时钟源 // 这里简化为直接使用默认时钟 } // 初始化SysTick定时器 (1ms中断) void SysTick_Init(void) { SysTick->LOAD = 400000 - 1; // 400MHz / 1000 = 400000 SysTick->VAL = 0; SysTick->CTRL = (1 << 2) | (1 << 1) | (1 << 0); // 使用处理器时钟,启用中断,启用计数器 } // 初始化USART8 void USART8_Init(uint32_t baudrate) { // 1. 使能时钟 GPIOE_CLK_EN(); USART8_CLK_EN(); // 2. 配置GPIO引脚 (PE0: RX, PE1: TX) GPIOE_MODER &= ~(3 << (0 * 2)); GPIOE_MODER |= (2 << (0 * 2)); GPIOE_OSPEEDR |= (3 << (0 * 2)); GPIOE_PUPDR |= (1 << (0 * 2)); GPIOE_AFRL &= ~(0xF << (0 * 4)); GPIOE_AFRL |= (8 << (0 * 4)); GPIOE_MODER &= ~(3 << (1 * 2)); GPIOE_MODER |= (2 << (1 * 2)); GPIOE_OSPEEDR |= (3 << (1 * 2)); GPIOE_PUPDR |= (1 << (1 * 2)); GPIOE_AFRL &= ~(0xF << (1 * 4)); GPIOE_AFRL |= (8 << (1 * 4)); // 3. 配置USART USART8_CR1 = 0; USART8_CR1 &= ~(1 << 28); USART8_CR1 &= ~(1 << 12); USART8_CR2 &= ~(0x3 << 12); USART8_CR1 &= ~(1 << 10); // 波特率计算 (PCLK2 = 200MHz) uint32_t usartdiv = 200000000 / baudrate; USART8_BRR = usartdiv; // 4. 启用USART USART8_CR1 |= (1 << 0); USART8_CR1 |= (1 << 2); USART8_CR1 |= (1 << 3); // 5. 配置中断 USART8_CR1 |= (1 << 5); NVIC_IPR8 |= (4 << 8); NVIC_ISER1 |= (1 << 8); } // USART8中断处理 void USART8_IRQHandler(void) { if (USART8_ISR & (1 << 5)) { volatile uint8_t data = USART8_RDR; // 这里可以处理接收到的数据 } } // 发送一个字符 void USART8_SendChar(char c) { while (!(USART8_ISR & (1 << 7))) {} USART8_TDR = c; } // 发送字符串 void USART8_SendString(const char *str) { while (*str) { USART8_SendChar(*str++); } } // 延时函数 (ms) void delay_ms(uint32_t ms) { uint32_t start = systick_counter; while ((systick_counter - start) < ms) {} } // 等待AT指令响应 uint8_t Wait_For_Response(const char *expected, uint32_t timeout) { uint32_t start = systick_counter; char response[128] = {0}; uint8_t index = 0; while ((systick_counter - start) < timeout) { if (USART8_ISR & (1 << 5)) { // 检查RXNE标志 char c = USART8_RDR; if (c == '\n' || index >= sizeof(response) - 1) { response[index] = '\0'; if (strstr(response, expected) != NULL) { return 1; // 找到预期响应 } index = 0; } else { response[index++] = c; } } } return 0; // 超时或未找到 } // 初始化4G模块 void Init_4G_Module(void) { // 1. 检查模块状态 USART8_SendString("AT\r\n"); if (!Wait_For_Response("OK", 1000)) { // 处理错误 return; } // 2. 检查SIM卡状态 USART8_SendString("AT+CPIN?\r\n"); if (!Wait_For_Response("+CPIN:READY", 2000)) { // 处理错误 return; } // 3. 设置APN USART8_SendString("AT+CGDCONT=1,\"IP\",\"CMIOT\"\r\n"); Wait_For_Response("OK", 1000); // 4. 激活PDP上下文 USART8_SendString("AT+CGACT=1,1\r\n"); Wait_For_Response("OK", 5000); // 5. 检查网络注册状态 USART8_SendString("AT+CREG?\r\n"); if (!Wait_For_Response("+CREG:0,1", 3000)) { // 处理错误 return; } // 6. 检查信号质量 USART8_SendString("AT+CSQ\r\n"); Wait_For_Response("OK", 1000); } // 连接MQTT代理 void Connect_MQTT_Broker(void) { // 1. 启动MQTT服务 USART8_SendString("AT+CMQTTSTART\r\n"); if (!Wait_For_Response("OK", 5000)) { // 处理错误 return; } // 2. 申请客户端 char accq_cmd[128]; snprintf(accq_cmd, sizeof(accq_cmd), "AT+CMQTTACCQ=0,\"%s\"\r\n", MQTT_CLIENT_ID); USART8_SendString(accq_cmd); Wait_For_Response("OK", 2000); // 3. 设置用户名和密码 char auth_cmd[256]; snprintf(auth_cmd, sizeof(auth_cmd), "AT+CMQTTUSERNAME=0,%lu,\"%s\"\r\n", strlen(MQTT_USERNAME), MQTT_USERNAME); USART8_SendString(auth_cmd); Wait_For_Response("OK", 2000); snprintf(auth_cmd, sizeof(auth_cmd), "AT+CMQTTPASSWORD=0,%lu,\"%s\"\r\n", strlen(MQTT_PASSWORD), MQTT_PASSWORD); USART8_SendString(auth_cmd); Wait_For_Response("OK", 2000); // 4. 连接MQTT代理 char conn_cmd[256]; snprintf(conn_cmd, sizeof(conn_cmd), "AT+CMQTTCONNECT=0,\"%s\",60,1\r\n", MQTT_SERVER); USART8_SendString(conn_cmd); if (!Wait_For_Response("OK", 10000)) { // 处理错误 return; } } // 生成模拟传感器数据 void Generate_Sensor_Data(SensorData *sensors, uint8_t count) { static uint32_t counter = 0; counter++; // 10个传感器ID uint32_t sensorIDs[10] = { 141705001, 151705001, 241705001, 251705001, 261705001, 271705001, 281705001, 301705001, 311705001, 321705001 }; for (uint8_t i = 0; i < count; i++) { sensors[i].id = sensorIDs[i]; // 生成模拟数据 (10-100之间的值) sensors[i].value = 10.0f + fmodf((counter * (i + 1)) * 1.23f, 90.0f); } } // 发送MQTT数据 void Send_MQTT_Data(SensorData *sensors, uint8_t count) { // 1. 设置主题 char topic_cmd[64]; snprintf(topic_cmd, sizeof(topic_cmd), "AT+CMQTTTOPIC=0,%lu\r\n", strlen(MQTT_TOPIC)); USART8_SendString(topic_cmd); Wait_For_Response(">", 1000); // 等待提示符 USART8_SendString(MQTT_TOPIC); USART8_SendString("\r\n"); Wait_For_Response("OK", 1000); // 2. 创建JSON负载 char payload[512] = "{ \"sensorDatas\": [ "; for (uint8_t i = 0; i < count; i++) { char sensorStr[64]; snprintf(sensorStr, sizeof(sensorStr), "{ \"sensorsId\": %lu, \"value\": \"%.1f\" }", sensors[i].id, sensors[i].value); strcat(payload, sensorStr); // 添加逗号分隔符(最后一个除外) if (i < count - 1) { strcat(payload, ", "); } } strcat(payload, " ] }"); // 3. 设置负载 char payload_cmd[64]; snprintf(payload_cmd, sizeof(payload_cmd), "AT+CMQTTPAYLOAD=0,%lu\r\n", strlen(payload)); USART8_SendString(payload_cmd); Wait_For_Response(">", 1000); // 等待提示符 USART8_SendString(payload); USART8_SendString("\r\n"); Wait_For_Response("OK", 1000); // 4. 发布消息 USART8_SendString("AT+CMQTTPUB=0,1,60\r\n"); Wait_For_Response("OK", 5000); } // 断开MQTT连接 void Disconnect_MQTT(void) { USART8_SendString("AT+CMQTTDISC=0,120\r\n"); Wait_For_Response("OK", 3000); USART8_SendString("AT+CMQTTREL=0\r\n"); Wait_For_Response("OK", 3000); USART8_SendString("AT+CMQTTSTOP\r\n"); Wait_For_Response("OK", 3000); } int main(void) { // 系统初始化 SystemClock_Config(); SysTick_Init(); USART8_Init(115200); // 初始化4G模块 Init_4G_Module(); // 连接MQTT代理 Connect_MQTT_Broker(); SensorData sensors[10]; uint32_t last_send = 0; while (1) { // 每10秒发送一次数据 if (systick_counter - last_send > 10000) { Generate_Sensor_Data(sensors, 10); Send_MQTT_Data(sensors, 10); last_send = systick_counter; } // 其他任务 delay_ms(100); } // 断开连接(实际可能不会执行到这里) Disconnect_MQTT(); return 0; } 需要加上通过串口看MQTT和4G模块连接状态,汉字要UTF-8的格式,把完整的代码发给我
11-28
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <signal.h> #include <time.h> #include <limits.h> #include <ctype.h> #define PORT 8080 #define WEB_ROOT "./www" #define BUFFER_SIZE 1024 #define MAX_REQUEST_SIZE (8 * 1024) // 8KB #define THREAD_POOL_SIZE 4 #define MAX_TASKS 1024 #define LOG_FILE_NAME "multi_thread.log" FILE *log_file; int server_socket; pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_t threads[THREAD_POOL_SIZE]; typedef struct { int socket; } task_t; typedef struct { task_t *tasks; int front, rear, count, max_tasks; pthread_mutex_t lock; pthread_cond_t cond; } task_queue_t; task_queue_t task_queue; void log_write(const char *format, ...) { va_list args; char buffer[1024]; va_start(args, format); vsnprintf(buffer, sizeof(buffer), format, args); va_end(args); pthread_mutex_lock(&log_mutex); fprintf(log_file, "%s", buffer); fflush(log_file); pthread_mutex_unlock(&log_mutex); } void task_queue_init(task_queue_t *q, int max_tasks) { q->tasks = malloc(sizeof(task_t) * max_tasks); q->front = q->rear = q->count = 0; q->max_tasks = max_tasks; pthread_mutex_init(&q->lock, NULL); pthread_cond_init(&q->cond, NULL); } void task_queue_push(task_queue_t *q, int socket) { pthread_mutex_lock(&q->lock); if (q->count >= q->max_tasks) { pthread_mutex_unlock(&q->lock); return; } q->tasks[q->rear].socket = socket; q->rear = (q->rear + 1) % q->max_tasks; q->count++; pthread_cond_signal(&q->cond); pthread_mutex_unlock(&q->lock); } int task_queue_pop(task_queue_t *q) { pthread_mutex_lock(&q->lock); while (q->count == 0) { pthread_cond_wait(&q->cond, &q->lock); } int socket = q->tasks[q->front].socket; q->front = (q->front + 1) % q->max_tasks; q->count--; pthread_mutex_unlock(&q->lock); return socket; } void *worker_thread(void *arg) { while (1) { int client_socket = task_queue_pop(&task_queue); handle_request(&client_socket); } } void send_response_header(int socket, int status, const char *content_type, int content_length, int keep_alive) { char response[BUFFER_SIZE] = {0}; char headers[BUFFER_SIZE] = {0}; snprintf(headers, sizeof(headers), "HTTP/1.1 %d ", status); switch (status) { case 200: strcat(headers, "OK\r\n"); break; case 404: strcat(headers, "Not Found\r\n"); break; default: strcat(headers, "Internal Server Error\r\n"); } snprintf(response, sizeof(response), "%sContent-Type: %s\r\n" "Content-Length: %d\r\n" "%s" "\r\n", headers, content_type, content_length, keep_alive ? "Connection: keep-alive\r\n" : "Connection: close\r\n"); send(socket, response, strlen(response), 0); } void handle_request(void *socket_ptr) { int client_socket = *((int *)socket_ptr); free(socket_ptr); char buffer[MAX_REQUEST_SIZE + 1] = {0}; int read_size = recv(client_socket, buffer, MAX_REQUEST_SIZE, 0); if (read_size <= 0) { log_write("Empty request or read error\n"); close(client_socket); return; } log_write("Request received:\n%s\n", buffer); char method[10], path[255], protocol[20]; if (sscanf(buffer, "%9s %254s %19s", method, path, protocol) != 3) { log_write("Invalid request format\n"); close(client_socket); return; } char full_path[PATH_MAX]; snprintf(full_path, sizeof(full_path), "%s%s", WEB_ROOT, path); char resolved_path[PATH_MAX]; if (realpath(full_path, resolved_path) == NULL || strncmp(resolved_path, WEB_ROOT, strlen(WEB_ROOT)) != 0) { log_write("Invalid path: %s\n", full_path); char *content = "<h1>403 Forbidden</h1>"; send_response_header(client_socket, 403, "text/html", strlen(content), 0); send(client_socket, content, strlen(content), 0); close(client_socket); return; } struct stat st; if (stat(resolved_path, &st) != 0 || S_ISDIR(st.st_mode)) { log_write("Directory or invalid file: %s\n", resolved_path); char *content = "<h1>404 Not Found</h1>"; send_response_header(client_socket, 404, "text/html", strlen(content), 0); send(client_socket, content, strlen(content), 0); close(client_socket); return; } const char *content_type = "text/html"; char *ext = strrchr(resolved_path, '.'); if (ext) { if (strcasecmp(ext, ".html") == 0) content_type = "text/html"; else if (strcasecmp(ext, ".css") == 0) content_type = "text/css"; else if (strcasecmp(ext, ".js") == 0) content_type = "text/javascript"; else if (strcasecmp(ext, ".jpg") == 0) content_type = "image/jpeg"; else if (strcasecmp(ext, ".png") == 0) content_type = "image/png"; else if (strcasecmp(ext, ".gif") == 0) content_type = "image/gif"; } int file_fd = open(resolved_path, O_RDONLY); if (file_fd == -1) { char *content = "<h1>404 Not Found</h1>"; send_response_header(client_socket, 404, "text/html", strlen(content), 0); send(client_socket, content, strlen(content), 0); close(client_socket); return; } off_t file_size = lseek(file_fd, 0, SEEK_END); lseek(file_fd, 0, SEEK_SET); int keep_alive = (strstr(buffer, "Connection: keep-alive") != NULL); send_response_header(client_socket, 200, content_type, file_size, keep_alive); char send_buffer[BUFFER_SIZE]; ssize_t bytes_read; while ((bytes_read = read(file_fd, send_buffer, BUFFER_SIZE)) > 0) { write(client_socket, send_buffer, bytes_read); } close(file_fd); if (!keep_alive) close(client_socket); } void init_log(const char *log_filename) { log_file = fopen(log_filename, "a"); if (!log_file) { perror("Error opening log file"); exit(EXIT_FAILURE); } time_t now = time(NULL); struct tm *tm_info = localtime(&now); log_write("=== Server started ===\n"); log_write("Current time: %s", asctime(tm_info)); } void close_log() { time_t now = time(NULL); struct tm *tm_info = localtime(&now); log_write("Current time: %s", asctime(tm_info)); log_write("=== Server closed ===\n"); fclose(log_file); } void signal_handler(int sig) { log_write("Caught signal %d, exiting...\n", sig); close(server_socket); close_log(); exit(0); } int main() { signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGTSTP, signal_handler); init_log(LOG_FILE_NAME); struct sockaddr_in address; int addrlen = sizeof(address); if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("Socket creation failed"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); if (bind(server_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("Bind failed"); exit(EXIT_FAILURE); } if (listen(server_socket, 10) < 0) { perror("Listen failed"); exit(EXIT_FAILURE); } task_queue_init(&task_queue, MAX_TASKS); for (int i = 0; i < THREAD_POOL_SIZE; i++) { pthread_create(&threads[i], NULL, worker_thread, NULL); } log_write("Server listening on port %d\n", PORT); printf("Server listening on port %d\n", PORT); while (1) { int client_socket = accept(server_socket, (struct sockaddr *)&address, (socklen_t *)&addrlen); if (client_socket < 0) { perror("Accept failed"); continue; } int *socket_ptr = malloc(sizeof(int)); *socket_ptr = client_socket; task_queue_push(&task_queue, client_socket); } return 0; } 这个代码里面的PATHMAX是什么,没有宏定义
08-09
#include "stm32h7xx_hal.h" #include "usart.h" #include "usart7.h" #include "CRC16.h" #include "delay.h" #include "timer123.h" #include <string.h> #include <stdio.h> #include <stdarg.h> // 全局变量定义(串口1相关) UART_HandleTypeDef UartHandle; uint8_t ucTemp; extern uint8_t Rxflag; uart1_def rschuanko_1; uint16_t byte_tmp[2]; uint8_t huichuan_buff[]={0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00, 0x00 }; // 全局变量定义(4G模块相关) int qi_ti_in[10]={0x00}; uint16_t zhuanhuan; uint8_t a=0; uint8_t ucTemp8; UART_HandleTypeDef UartHandle8; uart8_def rschuanko_8; uint16_t byte_tmp8[2]; extern uint8_t Rxflag8; uint8_t usRxCount8; uint8_t ucaRxBuf8[13]; uint8_t chuanko8jiesho[2]; // 4G模块控制相关定义 #define EC20_UART &UartHandle8 // EC20模块使用UART8通信 #define DEBUG_UART &UartHandle // 调试串口改为串口1 #define APN "CMIOT" // 物联网卡APN #define MQTT_BROKER "tcp://118.190.157.186:61613" // MQTT服务器地址 #define MQTT_TOPIC "A/XZRS/0/1705001" // MQTT主题 #define MQTT_USER "system" // MQTT用户名 #define MQTT_PWD "jsjc@2025" // MQTT密码 // 数据上报JSON模板 const char *mqtt_payload = "{\n" "sensorDatas:\n" " [\n" " { sensorsId: 141705001,value:'1111'},\n" " ]\n" "}\n"; // 函数声明 void DEBUG_USART_Config(void); // 串口1配置函数 void USART1_IRQHandler(void); void rschuanko_1_uart1_tx(void); void rschuanko1_uart1_rx_timer_handle(void); void rschuanko_1_uart1_rx_handle(void); void DEBUG_USART_Config8(void); void UART8_IRQHandler(void); void rschuanko8_uart8_rx_timer_handle(void); void EC20_SendAT(const char *at_cmd, uint32_t timeout); uint8_t EC20_WaitResponse(const char *response, uint32_t timeout); void EC20_Init(void); void MQTT_Connect(void); void MQTT_Publish(const char *topic, const char *payload); void Debug_Print(const char *fmt, ...); // 串口1配置 void DEBUG_USART_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit; DEBUG_USART_RX_GPIO_CLK_ENABLE(); DEBUG_USART_TX_GPIO_CLK_ENABLE(); /* 配置串口1时钟源*/ RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1; RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2; HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit); /* 使能串口1时钟 */ DEBUG_USART_CLK_ENABLE(); /* 配置Tx引脚为复用功能 */ GPIO_InitStruct.Pin = DEBUG_USART_TX_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = DEBUG_USART_TX_AF; HAL_GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStruct); /* 配置Rx引脚为复用功能 */ GPIO_InitStruct.Pin = DEBUG_USART_RX_PIN; GPIO_InitStruct.Alternate = DEBUG_USART_RX_AF; HAL_GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStruct); /* 配置串口1模式 */ UartHandle.Instance = DEBUG_USART; UartHandle.Init.BaudRate = 9600; UartHandle.Init.WordLength = UART_WORDLENGTH_8B; UartHandle.Init.StopBits = UART_STOPBITS_1; UartHandle.Init.Parity = UART_PARITY_NONE; UartHandle.Init.Mode = UART_MODE_TX_RX; UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; UartHandle.Init.OverSampling = UART_OVERSAMPLING_16; UartHandle.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED; UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; HAL_UART_Init(&UartHandle); HAL_UART_Receive_IT(&UartHandle,&ucTemp,1); /*串口1中断初始化 */ HAL_NVIC_SetPriority(DEBUG_USART_IRQ, 2, 1); HAL_NVIC_EnableIRQ(DEBUG_USART_IRQ); } // UART8配置 void DEBUG_USART_Config8(void) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_UART8_CLK_ENABLE(); // TX引脚配置 PE1 GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF8_UART8; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); // RX引脚配置 PE0 GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Alternate = GPIO_AF8_UART8; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); // UART参数配置 UartHandle8.Instance = UART8; UartHandle8.Init.BaudRate = 9600; UartHandle8.Init.WordLength = UART_WORDLENGTH_8B; UartHandle8.Init.StopBits = UART_STOPBITS_1; UartHandle8.Init.Parity = UART_PARITY_NONE; UartHandle8.Init.Mode = UART_MODE_TX_RX; UartHandle8.Init.HwFlowCtl = UART_HWCONTROL_NONE; UartHandle8.Init.OverSampling = UART_OVERSAMPLING_16; UartHandle8.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED; UartHandle8.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; HAL_UART_Init(&UartHandle8); // 中断配置 HAL_UART_Receive_IT(&UartHandle8, &ucTemp8, 1); HAL_NVIC_SetPriority(UART8_IRQn, 4, 1); HAL_NVIC_EnableIRQ(UART8_IRQn); } // 串口1中断服务函数 void USART1_IRQHandler(void) { HAL_UART_IRQHandler(&UartHandle); } // UART8中断服务函数 void UART8_IRQHandler(void) { HAL_UART_IRQHandler(&UartHandle8); } // 串口接收回调函数(统一处理) void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == DEBUG_USART) // 串口1 { rschuanko_1_uart1_tx(); } else if(huart->Instance == UART8) // UART8 { rschuanko_8.rx8_data[rschuanko_8.rx8_num++] = ucTemp8; rschuanko_8.rx8_delay = 30; if(rschuanko_8.rx8_num >= sizeof(rschuanko_8.rx8_data)) rschuanko_8.rx8_num = 0; HAL_UART_Receive_IT(&UartHandle8, &ucTemp8, 1); } } // 串口1数据处理函数 void rschuanko_1_uart1_tx(void) { if(rschuanko_1.rx_complete_flag==0) { if(rschuanko_1.rx_num<15) { rschuanko_1.rx_data[rschuanko_1.rx_num] = ucTemp; rschuanko_1.rx_num++; rschuanko_1.rx_delay = 20; } else { rschuanko_1.rx_complete_flag=1; } } HAL_UART_Receive_IT(&UartHandle,&ucTemp,1); } // 串口1接收逻辑处理函数 void rschuanko_1_uart1_rx_handle(void) { if(rschuanko_1.rx_complete_flag) { if(rschuanko_1.rx_num ==15) { byte_tmp[0]=CRC16_Get((uint8_t *)rschuanko_1.rx_data,13); byte_tmp[0]=byte_tmp[0]+0x31; if((rschuanko_1.rx_data[14]==(byte_tmp[0]>>8))&&(rschuanko_1.rx_data[13]==(byte_tmp[0]&0x00ff))) { // 方法1:强制类型转换 memcpy(rschuanko_1.tx_data, (uint8_t*)rschuanko_1.rx_data, 13); // 方法2(备选):逐字节复制 // for(int i=0; i<13; i++) { // rschuanko_1.tx_data[i] = rschuanko_1.rx_data[i]; // } buff[5]=1; } } rschuanko_1.rx_complete_flag=0; rschuanko_1.rx_num=0; rschuanko_1.rx_delay =0; } } // 串口1定时器处理函数(10ms周期) void rschuanko1_uart1_rx_timer_handle(void) { if(rschuanko_1.rx_delay) { rschuanko_1.rx_delay--; if(rschuanko_1.rx_delay==0) { rschuanko_1.rx_complete_flag=1; } } } // UART8定时器处理函数(10ms周期) void rschuanko8_uart8_rx_timer_handle(void) { if(rschuanko_8.rx8_delay) { rschuanko_8.rx8_delay--; if(rschuanko_8.rx8_delay == 0) rschuanko_8.rx8_complete_flag = 1; } } // 调试信息打印函数(串口1输出) ///重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数 //int fputc(int ch, FILE *f) //{ // /* 发送一个字节数据到串口DEBUG_USART */ // HAL_UART_Transmit(DEBUG_UART, (uint8_t *)&ch, 1, 1000); // // return (ch); //} void Debug_Print(const char *fmt, ...) { char buf[256]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); strcat(buf, "\r\n"); HAL_UART_Transmit(DEBUG_UART, (uint8_t*)buf, strlen(buf), 1000); } // 发送AT指令 void EC20_SendAT(const char *at_cmd, uint32_t timeout) { HAL_UART_Transmit(EC20_UART, (uint8_t*)at_cmd, strlen(at_cmd), timeout); Debug_Print("fa song zhi ling: %s", at_cmd); } // 等待EC20响应 uint8_t EC20_WaitResponse(const char *response, uint32_t timeout) { uint32_t tickstart = HAL_GetTick(); while((HAL_GetTick() - tickstart) < timeout) { if(rschuanko_8.rx8_complete_flag) { rschuanko_8.rx8_data[rschuanko_8.rx8_num] = '\0'; Debug_Print("mo kuai xiang ying: %s", rschuanko_8.rx8_data); if(strstr((char*)rschuanko_8.rx8_data, response) != NULL) { memset(rschuanko_8.rx8_data, 0, sizeof(rschuanko_8.rx8_data)); rschuanko_8.rx8_num = 0; rschuanko_8.rx8_complete_flag = 0; return 1; } memset(rschuanko_8.rx8_data, 0, sizeof(rschuanko_8.rx8_data)); rschuanko_8.rx8_num = 0; rschuanko_8.rx8_complete_flag = 0; } } return 0; } // EC20模块初始化 void EC20_Init(void) { Debug_Print("kai shi chu shi hua..."); EC20_SendAT("AT\r\n", 1000); if(!EC20_WaitResponse("OK", 2000)) { Debug_Print("模块未响应AT指令!"); return; } char apn_cmd[32]; sprintf(apn_cmd, "AT+CGDCONT=1,\"IP\",\"%s\"\r\n", APN); EC20_SendAT(apn_cmd, 1000); if(!EC20_WaitResponse("OK", 2000)) { Debug_Print("设置APN失败!"); return; } EC20_SendAT("AT+CGACT=1,1\r\n", 1000); if(!EC20_WaitResponse("OK", 5000)) { Debug_Print("激活PDP失败!"); return; } EC20_SendAT("AT+CREG?\r\n", 1000); if(EC20_WaitResponse("0,1", 2000) || EC20_WaitResponse("0,5", 2000)) { Debug_Print("网络注册成功!"); } else { Debug_Print("网络注册失败!"); return; } Debug_Print("EC20模块初始化完成!"); } // MQTT连接配置 void MQTT_Connect(void) { Debug_Print("开始连接MQTT服务器..."); char mqtt_server[64]; sprintf(mqtt_server, "AT+QMTCFG=\"broker\",0,\"%s\"\r\n", MQTT_BROKER); EC20_SendAT(mqtt_server, 1000); if(!EC20_WaitResponse("OK", 3000)) { Debug_Print("设置MQTT服务器失败!"); return; } char mqtt_auth[64]; sprintf(mqtt_auth, "AT+QMTCFG=\"auth\",0,\"%s\",\"%s\"\r\n", MQTT_USER, MQTT_PWD); EC20_SendAT(mqtt_auth, 1000); if(!EC20_WaitResponse("OK", 3000)) { Debug_Print("设置MQTT认证失败!"); return; } EC20_SendAT("AT+QMTOPEN=0\r\n", 1000); if(!EC20_WaitResponse("+QMTOPEN: 0,0", 10000)) { Debug_Print("MQTT连接失败!"); return; } EC20_SendAT("AT+QMTCONN=0,\"STM32_EC20_Client\"\r\n", 1000); if(!EC20_WaitResponse("+QMTCONN: 0,0,0", 5000)) { Debug_Print("MQTT客户端连接失败!"); return; } Debug_Print("MQTT服务器连接成功!"); } // MQTT发布消息 void MQTT_Publish(const char *topic, const char *payload) { Debug_Print("发布MQTT消息..."); char publish_cmd[1024]; // 补充payload参数,格式为:AT+QMTPUB=0,0,0,主题长度,"主题","消息内容"\r\n // 注意:主题长度可以用strlen(topic)获取 sprintf(publish_cmd, "AT+QMTPUB=0,0,0,%d,\"%s\",\"%s\"\r\n", strlen(topic), // 主题长度 topic, // 第一个参数:主题 payload); // 第二个参数:消息内容 EC20_SendAT(publish_cmd, 1000); if(EC20_WaitResponse(">", 2000)) { HAL_UART_Transmit(EC20_UART, (uint8_t*)payload, strlen(payload), 5000); HAL_UART_Transmit(EC20_UART, (uint8_t*)"\x1A", 1, 1000); if(EC20_WaitResponse("+QMTPUB: 0,0,0", 5000)) { Debug_Print("MQTT消息发布成功!"); } else { Debug_Print("MQTT消息发布失败!"); } } } //// 系统时钟配置函数 //void SystemClock_Config(void) //{ // RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // __HAL_RCC_PWR_CLK_ENABLE(); // __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); // RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // RCC_OscInitStruct.HSEState = RCC_HSE_ON; // RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // RCC_OscInitStruct.PLL.PLLM = 25; // RCC_OscInitStruct.PLL.PLLN = 400; // RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // RCC_OscInitStruct.PLL.PLLQ = 8; // if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) // { // Error_Handler(); // } // RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK // |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; // RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) // { // Error_Handler(); // } //} //// 错误处理函数 //void Error_Handler(void) //{ // while(1) // { // HAL_Delay(500); // } //} // 主函数 int main(void) { HAL_Init(); //初始化HAL库 Stm32_Clock_Init(); //设置时钟,400Mhz // Stm32_Clock_Init(160,5,2,4); //设置时钟,400Mhz delay_init(400);//延时初始化 // 初始化串口1(调试用)和UART8(EC20模块) DEBUG_USART_Config(); DEBUG_USART_Config8(); // 定时器初始化(10ms中断) timx_int_init123(50 - 1, 200- 1); // 初始化变量 memset(&rschuanko_1, 0, sizeof(rschuanko_1)); memset(&rschuanko_8, 0, sizeof(rschuanko_8)); // printf("系统启动成功!"); // EC20模块初始化 EC20_Init(); // 连接MQTT服务器 MQTT_Connect(); // 主循环 while(1) { // 处理串口1接收数据 rschuanko_1_uart1_rx_handle(); // 每隔10秒发布MQTT消息 MQTT_Publish(MQTT_TOPIC, mqtt_payload); HAL_Delay(10000); } } //#ifdef USE_FULL_ASSERT //void assert_failed(uint8_t *file, uint32_t line) //{ //} //#endif上面的错误调试信息一个字都没有在串口调试工具上显示,帮我修改一下,看是哪里的问题,串口一数据回显没有问题,不用printf,只用Debug_Print函数
12-02
我用多线程编写了一个webserver,帮我分析并优化一下: /* Copyright(c) 2008-2024 ChengDu TP-LINK Technologies Co.Ltd. * * file multi_thread.c * brief Construct a webserver using a multi-thread approach * author Wang Junhang * version 0.0.0 * date 2025-08-07 * * history */ /************************************Include Files**********************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <signal.h> #include <time.h> /***********************************************************************************/ /* DEFINES */ /***********************************************************************************/ #define PORT 8080 /* Socket Port */ #define WEB_ROOT "./www" /* Server root directory */ #define BUFFER_SIZE 1024 #define MAX_SOCKET_CONN 10 /*Maximum number of socket connections*/ #define LOG_FILE_NAME "multi_thread.log" /***********************************************************************************/ /* TYPES */ /***********************************************************************************/ /***********************************************************************************/ /* EXTERN_PROTOTYPES */ /***********************************************************************************/ /***********************************************************************************/ /* LOCAL_PROTOTYPES */ /***********************************************************************************/ /***********************************************************************************/ /* VARIABLES */ /***********************************************************************************/ FILE *log_file; /* Global variable for log file pointer */ int server_socket; /* Global server socket file descriptor */ time_t now; /* Global time */ struct tm *tm_info; /***********************************************************************************/ /* LOCAL_FUNCTIONS */ /***********************************************************************************/ /***********************************************************************************/ /* PUBLIC_FUNCTIONS */ /***********************************************************************************/ void *handle_request(void *socket_ptr); void send_response_header(int socket, int status, char *content_type); void init_log(const char *log_filename); void close_log(); void signal_handler(int sig); void cleanup(); /***********************************************************************************/ /* GLOBAL_FUNCTIONS */ /***********************************************************************************/ int main() { signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGTSTP, signal_handler); init_log(LOG_FILE_NAME); int client_socket; struct sockaddr_in address; int addrlen = sizeof(address); if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("Socket creation failed"); exit(EXIT_FAILURE); } /* Forcefully attaching socket to the defined port */ address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); if (bind(server_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("Bind failed"); exit(EXIT_FAILURE); } if (listen(server_socket, MAX_SOCKET_CONN) < 0) { perror("Listen failed"); exit(EXIT_FAILURE); } printf("Server listening on port %d\n", PORT); fprintf(log_file, "Server listening on port %d\n\r\n", PORT); /* recording start to log */ /* Accept incoming connections and handle in separate threads */ while (1) { if ((client_socket = accept(server_socket, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) { perror("Accept failed"); exit(EXIT_FAILURE); } /* Create a new thread to handle the client */ pthread_t thread; int *socket_ptr = malloc(sizeof(int)); *socket_ptr = client_socket; if (pthread_create(&thread, NULL, handle_request, (void *)socket_ptr) < 0) { perror("Thread creation failed"); exit(EXIT_FAILURE); } pthread_detach(thread); /* Detach the thread to avoid memory leaks */ } cleanup(); return 0; } /* * fn void *handle_request(void *socket_ptr) * brief Respond to HTTP requests based on different request methods (GET/POST/OTHERS). * details * param[in] socket_ptr The pointer of connected socket * * return NULL * retval NULL * * note */ void *handle_request(void *socket_ptr) { int client_socket = *((int *)socket_ptr); free(socket_ptr); /* release the pointer of client socket*/ int read_size; char buffer[BUFFER_SIZE] = {0}; char method[10], path[255], protocol[20]; read_size = read(client_socket, buffer, sizeof(buffer)); if (read_size <= 0) { perror("Read failed"); return; } fprintf(log_file, "Request received:\n%s\r\n", buffer); /* recording request to log */ if (strstr(buffer, "GET") != NULL) { sscanf(buffer, "%s %s %s", method, path, protocol); printf("Received request:\n%s\n", buffer); if (strcmp(path, "/") == 0) { char tmp_path_1[64], tmp_path_2[64]; snprintf(tmp_path_1, sizeof(tmp_path_1), "%s%s", WEB_ROOT, "/index.html"); snprintf(tmp_path_2, sizeof(tmp_path_1), "%s%s", WEB_ROOT, "/Index.html"); if (access(tmp_path_1, F_OK) != -1) { sprintf(path, "/index.html"); } else if (access(tmp_path_2, F_OK) != -1) { sprintf(path, "/Index.html"); } else { } } /* Construct full file path (prepend ./www) */ char full_path[256]; snprintf(full_path, sizeof(full_path), "%s%s", WEB_ROOT, path); int file_fd = open(full_path, O_RDONLY); if (file_fd == -1) { fprintf(log_file, "Error opening file: %s\r\n", full_path); char *content_type = "text/html"; char *content = "<h1>404 Not Found</h1>"; send_response_header(client_socket, 404, content_type); send(client_socket, content, strlen(content), 0); } else { off_t file_size = lseek(file_fd, 0, SEEK_END); lseek(file_fd, 0, SEEK_SET); printf("Content is:%d:\r\n", file_size); char *content_type = "text/html"; if (strstr(full_path, ".png")) content_type = "image/png"; if (strstr(full_path, ".jpg")) content_type = "image/jpeg"; if (strstr(full_path, ".gif")) content_type = "image/gif"; if (strstr(full_path, ".html")) content_type = "text/html"; if (strstr(full_path, ".css")) content_type = "text/css"; if (strstr(full_path, ".json")) content_type = "text/javascript"; if (strstr(full_path, ".js")) content_type = "text/javascript"; send_response_header(client_socket, 200, content_type); /* Send response content */ char send_buffer[BUFFER_SIZE]; ssize_t bytes_read; while ((bytes_read = read(file_fd, send_buffer, BUFFER_SIZE)) > 0) { write(client_socket, send_buffer, bytes_read); } close(file_fd); fprintf(log_file, "Response file: %s\r\n", full_path); } } else if (strstr(buffer, "POST") != NULL) { /* Handle POST requests */ char *content_length_header = strstr(buffer, "Content-Length:"); int content_length = 0; if (content_length_header != NULL) { content_length = atoi(content_length_header + 15); // Skip "Content-Length:" to get the value } /* Read POST data */ char post_content_buffer[BUFFER_SIZE] = {0}; int total_read = 0; while ((read_size = recv(client_socket, post_content_buffer, 1024, 0)) > 0) { total_read += read_size; if (total_read >= content_length) { break; } } printf("Post data is:\r\n%s:\r\n\r\n", post_content_buffer); fprintf(log_file, "Post data is: %s\r\n", post_content_buffer); /* Process the received data (in buffer) Here, you can handle the POST data according to your application's logic For simplicity, we just send a response indicating the data was received*/ /* Send Response for POST request */ char *content_type = "text/html"; char *content = "<h1> Post Response</h1>"; send_response_header(client_socket, 200, content_type); send(client_socket, content, strlen(content), 0); } else { /* Send Error Response */ char *content_type = "text/html"; char *content = "<h1>500 Internal Server Error</h1>"; send_response_header(client_socket, 500, content_type); send(client_socket, content, strlen(content), 0); fprintf(log_file, "500 Sever can't serve this type of request\r\n"); /* recording error to log */ } close(client_socket); /* close the client socket file describer*/ return NULL; } /* * fn void send_response_header(int socket, int status, char *content_type) * brief Send the response header to the client * details * param[in] socket The file describer of connected socket * param[in] status Http response status * param[in] content_type The type of response * * param[out] None None * * return None * retval None None * * note */ void send_response_header(int socket, int status, char *content_type) { char response[BUFFER_SIZE] = {0}; char headers[BUFFER_SIZE] = {0}; sprintf(headers, "HTTP/1.1 %d ", status); switch (status) { case 200: strcat(headers, "OK\r\n"); break; case 404: strcat(headers, "Not Found\r\n"); break; default: strcat(headers, "Internal Server Error\r\n"); } /* Send HTTP response header */ sprintf(response, "%sContent-Type: %s\r\n\r\n", headers, content_type); send(socket, response, strlen(response), 0); } /* * brief init the log file */ void init_log(const char *log_filename) { log_file = fopen(log_filename, "a"); if (log_file == NULL) { perror("Error opening log file"); exit(EXIT_FAILURE); } time(&now); tm_info = localtime(&now); fprintf(log_file, "=== Server started ===\n"); fprintf(log_file, "Current time: %s", asctime(tm_info)); } /* * brief close the log file */ void close_log() { time(&now); tm_info = localtime(&now); fprintf(log_file, "Current time: %s", asctime(tm_info)); fprintf(log_file, "=== Server closed ===\n\r\n"); fclose(log_file); } /* * brief process exit signal */ void signal_handler(int sig) { printf("\rCaught signal %d, exiting...\n", sig); fprintf(log_file, "Caught signal %d, exiting...\n", sig); cleanup(); exit(0); } /* * brief clean all resources */ void cleanup() { close(server_socket); close_log(); }
08-09
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> #include <pthread.h> #include <fcntl.h> #include <sys/stat.h> #include <errno.h> #define PORT 8082 #define WEB_DIR "/home/zts/testcode/httpserver/web" #define BUFFER_SIZE 4096 // 增大缓冲区以支持 POST 请求 // 获取文件 MIME 类型 const char *get_content_type(const char *path) { const char *ext = strrchr(path, '.'); if (ext) { if (strcmp(ext, ".html") == 0) return "text/html"; if (strcmp(ext, ".css") == 0) return "text/css"; if (strcmp(ext, ".js") == 0) return "application/javascript"; if (strcmp(ext, ".png") == 0) return "image/png"; if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0) return "image/jpeg"; if (strcmp(ext, ".gif") == 0) return "image/gif"; } return "application/octet-stream"; } // 读取文件内容到缓冲区 char *read_file(const char *path, long *size) { FILE *file = fopen(path, "rb"); if (!file) return NULL; fseek(file, 0, SEEK_END); *size = ftell(file); fseek(file, 0, SEEK_SET); char *buffer = malloc(*size); if (!buffer) { fclose(file); return NULL; } fread(buffer, 1, *size, file); fclose(file); return buffer; } // 发送 404 错误响应 void send_404(int client_socket) { const char *response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\nContent-Length: 13\r\n\r\n404 Not Found"; send(client_socket, response, strlen(response), 0); } // 发送 200 OK 响应并显示提交信息 void send_post_response(int client_socket, const char *name, const char *email, const char *message) { char response[4096]; snprintf(response, sizeof(response), "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n" "Content-Length: %d\r\n" "\r\n" "<html><body>" "<h2>Submitted Data:</h2>" "<p><b>Name:</b> %s</p>" "<p><b>Email:</b> %s</p>" "<p><b>Message:</b> %s</p>" "<a href=\"/\">Back</a>" "</body></html>", strlen("<html><body><h2>Submitted Data:</h2>") + strlen("<p><b>Name:</b> ") + strlen(name) + strlen("</p><p><b>Email:</b> ") + strlen(email) + strlen("</p><p><b>Message:</b> ") + strlen(message) + strlen("</p><a href=\"/\">Back</a></body></html>"), name, email, message); send(client_socket, response, strlen(response), 0); } // 解析 POST 数据 void parse_post_data(const char *data, char *name, char *email, char *message) { char *dup = strdup(data); char *pair, *saveptr; for (pair = strtok_r(dup, "&", &saveptr); pair; pair = strtok_r(NULL, "&", &saveptr)) { char *key = strtok(pair, "="); char *value = strtok(NULL, "="); if (!value) value = ""; if (strcmp(key, "name") == 0) { strncpy(name, value, 256); } else if (strcmp(key, "email") == 0) { strncpy(email, value, 256); } else if (strcmp(key, "message") == 0) { strncpy(message, value, 1024); } } free(dup); } // 处理客户端请求 void *handle_client(void *arg) { int client_socket = *((int *)arg); free(arg); char buffer[BUFFER_SIZE]; int bytes_read = recv(client_socket, buffer, BUFFER_SIZE - 1, 0); if (bytes_read <= 0) { close(client_socket); return NULL; } buffer[bytes_read] = '\0'; // 解析请求路径 char method[16], path[256], protocol[16]; sscanf(buffer, "%15s %255s %15s", method, path, protocol); // 处理 GET 请求 if (strcmp(method, "GET") == 0) { // 构造文件路径 char file_path[512]; snprintf(file_path, sizeof(file_path), "%s%s", WEB_DIR, path); if (file_path[strlen(file_path) - 1] == '/') { strcat(file_path, "Index.html"); } // 读取文件 long file_size; char *file_content = read_file(file_path, &file_size); if (!file_content) { send_404(client_socket); close(client_socket); return NULL; } // 构建响应头 const char *content_type = get_content_type(file_path); char header[512]; snprintf(header, sizeof(header), "HTTP/1.1 200 OK\r\n" "Content-Type: %s\r\n" "Content-Length: %ld\r\n" "\r\n", content_type, file_size); // 发送响应 send(client_socket, header, strlen(header), 0); send(client_socket, file_content, file_size, 0); free(file_content); close(client_socket); } // 处理 POST 请求 else if (strcmp(method, "POST") == 0) { // 获取 Content-Length int content_length = 0; char *cl = strstr(buffer, "Content-Length: "); if (cl) { sscanf(cl, "Content-Length: %d", &content_length); } // 提取 POST 数据 char post_data[4096] = {0}; char *body_start = strstr(buffer, "\r\n\r\n") + 4; int body_len = buffer + bytes_read - body_start; memcpy(post_data, body_start, body_len); int remaining = content_length - body_len; while (remaining > 0) { int read = recv(client_socket, buffer, BUFFER_SIZE - 1, 0); if (read <= 0) break; memcpy(post_data + body_len, buffer, read); body_len += read; remaining -= read; } post_data[body_len] = '\0'; // 解析并打印数据 char name[256] = {0}, email[256] = {0}, message[1024] = {0}; parse_post_data(post_data, name, email, message); // 打印提交信息 printf("Received POST data:\n"); printf("Name: %s\n", name); printf("Email: %s\n", email); printf("Message: %s\n", message); // 发送响应 send_post_response(client_socket, name, email, message); close(client_socket); } else { const char *response = "HTTP/1.1 501 Not Implemented\r\n\r\n"; send(client_socket, response, strlen(response), 0); close(client_socket); } return NULL; } int main() { int server_socket, client_socket; struct sockaddr_in server_addr, client_addr; socklen_t client_len = sizeof(client_addr); // 创建 socket server_socket = socket(AF_INET, SOCK_STREAM, 0); if (server_socket < 0) { perror("Socket creation failed"); exit(EXIT_FAILURE); } // 设置地址复用 int opt = 1; setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // 绑定地址和端口 server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(PORT); if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("Bind failed"); close(server_socket); exit(EXIT_FAILURE); } // 监听连接 if (listen(server_socket, 10) < 0) { perror("Listen failed"); close(server_socket); exit(EXIT_FAILURE); } printf("Server running on http://localhost:%d\n", PORT); while (1) { client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_len); if (client_socket < 0) { perror("Accept failed"); continue; } // 创建线程处理客户端 pthread_t thread_id; int *pclient = malloc(sizeof(int)); *pclient = client_socket; if (pthread_create(&thread_id, NULL, handle_client, pclient) != 0) { perror("Thread creation failed"); free(pclient); close(client_socket); } else { pthread_detach(thread_id); // 自动回收线程资源 } } close(server_socket); return 0; } 能基于上述内容 写一个日志系统吗
08-09
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值