- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想发送 ICMP 消息并接收回显。我花了一周的时间研究原始套接字并搜索引用资料。然后我编写下面的代码来保证发送ICMP消息成功,因为'socket'和'send'的返回是可以的(不是负1)。不幸的是,“recvfrom”什么也没收到,下面是我在 Windows 上的简洁代码:
#define _WIN32_WINNT 0x501
#include <stdio.h>
#include <ws2tcpip.h>
#include <winsock2.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#pragma comment(lib,"Ws2_32.lib")
WSADATA wsaData;
int main(int args, char *argv[]){
WSAStartup(MAKEWORD(2,2),&wsaData);
//**************icmp book******************/
typedef struct icmp_hdr {
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short icmp_checksum;
unsigned short icmp_id;
unsigned short icmp_sequence;
unsigned long icmp_timestamp;
} ICMP_HDR;
ICMP_HDR *icmp = NULL;
char buffer[sizeof(ICMP_HDR) + 32];
icmp = (ICMP_HDR *)buffer; //
icmp->icmp_type = 8;
icmp->icmp_code = 0;
icmp->icmp_id = 1314;
icmp->icmp_checksum = sizeof(ICMP_HDR) + 32;
icmp->icmp_sequence = 0;
icmp->icmp_timestamp = GetTickCount();
memset(&buffer[sizeof(ICMP_HDR)],'@',32);
int my_socket = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
struct in_addr my_addr;
my_addr.s_addr = inet_addr("127.0.0.1");
// inet_aton(argv[1],&my_addr);
struct sockaddr_in sa_t;
sa_t.sin_family = AF_INET;
sa_t.sin_port = htons(0);
sa_t.sin_addr = my_addr;
int p = sendto(my_socket,buffer,sizeof(ICMP_HDR)+32,0,(struct sockaddr *)&sa_t, sizeof(sa_t));
printf("return : %d\n ------s: %d\n",p,my_socket);
int tmp_add = sizeof(sa_t);
char buf[1024];
recvfrom(my_socket,buf,1024,0,(struct sockaddr *)&sa_t,&tmp_add);
printf("receive is: %s\n",buf);
return 1;
}
当我编译并运行此代码时,我的期望是“recvfrom”函数将收到任何内容。
但是“recvfrom”没有任何结果,我花了两天时间,在这里谢谢。
最佳答案
首先,您需要确保编译器不会尝试在 4、8 或 16 字节地址边界上对齐所有内容(#pragma pack
)来填充您的结构,然后您必须正确对齐构造并正确计算校验和。在响应端,您不能将缓冲区视为字符串,它可能包含非 ASCII 数据。此外,网络字节顺序并不总是与任一主机体系结构上的字节顺序相同,因此您应该始终在发送/接收之前进行转换。
这有效。我将让您弄清楚响应中额外的 20 个左右字节的含义。
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ws2tcpip.h>
#include <winsock2.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#pragma comment(lib,"Ws2_32.lib")
#define STRING_LENGTH 32
//**************icmp book******************/
#pragma pack(push, 1)
typedef struct icmp_msg {
uint8_t type;
uint8_t code;
uint16_t checksum;
uint16_t id;
uint16_t sequence;
uint32_t timestamp;
uint8_t tail[STRING_LENGTH + 2];
} ICMP_MSG;
#pragma pack(pop)
// malloc() is gauranteed to provide suitable alignement.
ICMP_MSG *ping = NULL;
void PrintMsg(ICMP_MSG *msg)
{
printf("Ping:\n\tId: %u16\n\tSequence: %u16\n\tTimestamp: %lu\n\tString: ", ntohs(msg->id), ntohs(msg->sequence), ntohl(msg->timestamp));
char *it = (char*)&(msg->tail[0]);
char *it_end = (char*)msg + sizeof(ICMP_MSG);
while (it < it_end)
{
char *hexString[65] = { 0 };
_itoa_s(*it, (char*)hexString, 32, 16);
printf("0x%s,", (char*)hexString);
it++;
}
printf("\n\n");
}
// Ripped from https://github.com/pocoproject/poco/blob/develop/Net/src/ICMPPacketImpl.cpp#L98 and cleaned-up.
uint16_t Checksum(uint16_t *addr, size_t len)
{
size_t nleft = len;
uint16_t* w = addr;
uint16_t answer;
int32_t sum = 0;
while (nleft > 1)
{
sum += *w++;
nleft -= sizeof(uint16_t);
}
if (nleft == 1)
{
uint16_t u = 0;
*(uint8_t*)(&u) = *(uint8_t*)w;
sum += u;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum & 0xffff;
return answer;
}
int main(void) {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
ping = malloc(sizeof(ICMP_MSG));
ping->type = 8;
ping->code = 0;
ping->id = htons(1314);
ping->checksum = 0; // Must be zero prior to checksum calculation.
ping->sequence = 0;
ping->timestamp = htonl(GetTickCount());
// 0x40 == '@' in ASCII
memset(ping->tail, 0x40, STRING_LENGTH);
// NUL pad the last two bytes fo the string.
ping->tail[STRING_LENGTH] = '\0';
ping->tail[STRING_LENGTH + 1] = '\0';
ping->checksum = Checksum((uint16_t*)ping, sizeof(ICMP_MSG));
int res;
int my_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
struct in_addr my_addr;
my_addr.s_addr = inet_addr("127.0.0.1");
//res = inet_pton(AF_INET, "127.0.0.1", &my_addr.s_addr);
struct sockaddr_in sa_t;
sa_t.sin_family = AF_INET;
sa_t.sin_port = htons(0);
sa_t.sin_addr = my_addr;
PrintMsg(ping);
res = sendto(my_socket, (const char*)ping, sizeof(ICMP_MSG), 0, (struct sockaddr *)&sa_t, sizeof(sa_t));
printf("Socket: %d\nsendto returned: %d\n", my_socket, res);
int tmp_add = sizeof(sa_t);
ICMP_MSG *resp = calloc(1, 2048 /*sizeof(ICMP_MSG)*/);
res = recvfrom(my_socket, (char*)resp, 2048, 0, (struct sockaddr *)&sa_t, &tmp_add);
printf("recvfrom returned: %d\n", res);
if (SOCKET_ERROR == res)
{
res = WSAGetLastError();
printf("WSAGetLastError() returned: %d (", res);
switch (res)
{
case WSAEMSGSIZE:
printf("WSAMSGSIZE)\n");
break;
default:
printf("Unexpected)\n");
break;
}
}
PrintMsg(resp);
system("pause");
free(ping);
free(resp);
return 1;
}
关于c - 发送 ICMP 消息但没有收到任何消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49102067/
在 ICMP 套接字上接收时(SOCK_RAW 和 IPPROTO_ICMP),因为ICMP协议(protocol)中没有“端口”的概念,怎么能应用程序确定接收到的数据包不是其他数据包的一部分TCP/
我正在 Linux 中进行一些有关路径 MTU 发现的实验。据我从 RFC 1191 中了解到,如果路由器收到一个具有非零 DF 位的数据包,并且该数据包无法在没有分段的情况下发送到下一个主机,那么路
我正在尝试使用 POX Controller 向交换机添加流条目,我的代码是: fm = of.ofp_flow_mod() fm.match.in_port = 1 fm.p
我试图用 iptables 保护 Smurf 攻击。与 iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DR
我正在从一台 PC 向另一台 PC 发送 UDP 数据包。我正在使用 Wire Shark 观看整个事件。我注意到有一段时间从一个系统到另一个系统的数据包传输顺畅。然后突然ICMP数据包错误 'por
介绍 为了更有效地转发IP数据报和提高交付成功的机会,在网际层使用了网际控制报文协议 ICMP(Internet Control Message Protocol) ICMP是互联网的标准协议 ICM
介绍 为了更有效地转发IP数据报和提高交付成功的机会,在网际层使用了网际控制报文协议 ICMP(Internet Control Message Protocol) ICMP是互联网的标准协议 ICM
如果相关 NAT 设备重写出站 ICMP 数据包,ICMP NAT 穿越应该如何工作? 图表 =====================================================
我感兴趣的基本代码序列是(伪代码) sendto(some host); // host may be unreachable for now which is normal ... if(selec
我目前正在开发基于 Go 的路由器以用于教育目的。 当尝试序列化我从主机转发的 ICMP 数据包时,gopacket.ICMPv4 结构的 .SerializeTo 函数似乎正在剥离 ICMP 有效负
有人可以解释为什么ICMP回声数据包的最大合法大小计算如下: 65535 - 20 - 8 = 65507 谢谢。 最佳答案 65535 字节是 IPv4 网络数据包的最大允许大小,而 20 和 8
我一直在使用 jedie's python ping implementation在 Windows 上。我可能是错的,但是当从不同的线程 ping 两台计算机(A 和 B)时,ping 将返回它收到
我在 x64 机器上。以下是我计算 ICMP 校验和的方法: unsigned short in_checksum(unsigned short *ptr, int n_bytes) { regi
我正在尝试使用与 tcp 和 udp 相同的技术对 icmp 数据包进行校验和,但它得到错误的校验和,你能告诉我我的问题在哪里吗? ICMP_HEADER *icmpheader =
我重用了这个 site 中的原始套接字片段并删除了 TCP 部分并添加了我的 ICMP 部分以请求回显。我的两台机器都在同一个局域网上,运行 Ubuntu 32 位。我给了校验和函数我的 ICMP 指
当类型为 11 时,即超出时间,ICMP 数据包负载的大小是多少? 由于它包含一个 IP header 和生成 ICMP 消息的 IP 数据包有效载荷的前 8 个字节,我认为它的大小是 20 + 8
我知道 ICMP 请求包含 IP 地址。客户端 MAC 地址是否包含在 ICMP 请求中? ping 请求中包含哪些其他信息(如果有)? 最佳答案 ICMP“ping”数据包,正式称为“echo re
当校验和应包括数据部分,数据部分的大小可以是可变的,并且无法预测数据大小时,如何计算 ICMP 回显请求或回复的校验和? 这是documentation关于如何计算 ICMP header 的校验和。
作为家庭作业的一部分,我必须在 Linux 中编写一个 C 程序,该程序使用原始套接字生成对 ICMP Echo 请求的 ICMP 回复。 ICMP 数据包中的数据是否也必须包含在校验和中?还是应该只
以下代码是对从 icmp dll 调用的 IcmpPing 例程的测试。在调试中它工作正常,但在发布中它会抛出错误。该错误是由“IcmpCloseHandle”调用引起的,因为调用 IcmpSendE
我是一名优秀的程序员,十分优秀!