如果目标不存在,sendto() 不会产生错误
sendto() does not generate error if destination does not exist
我正在使用 C 中的 sendto()
函数。我已经设置了目标地址和目标端口。在发送 UDP 帧时,我可以在 Wireshark 中看到帧,并且 Wireshark 显示的数据包数量与我在程序中定义的完全相同。
问题是即使无法到达目标地址,帧仍在发送,我可以在 Wireshark 中看到它。
如果目标 IP 不存在,sendto()
函数不应该生成错误吗?
if (sendto(sockfd, &buffer[i], UDP_FRAME, 0,
(const struct sockaddr*)&server, sizeof(server)) < 0)
{
fprintf(stderr, "Error in sendto()\n");
//return EXIT_FAILURE;
}
目的地。 IP:234.168.0.1
目标端口:80 或 9(丢弃协议)
#define PORT (80)
#define FRAMES (20000)
#define UDP_FRAME (1442)
#define SERVERADDRESS "234.168.0.1"
#define BUFFER_SIZE (FRAMES * UDP_FRAME)
char buffer[BUFFER_SIZE];
int main(int argc, char **argv)
{
struct timespec start, end, loop_start, loop_end;
int sockfd, count_frame = 0, frames_total, i = UDP_FRAME, n=1;
struct sockaddr_in server;
printf("Build Data...\n");
build(buffer, sizeof(buffer));
printf("Configure socket...\n");
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
fprintf(stderr, "Error opening socket");
return EXIT_FAILURE;
}
/*----------------------------------------------------*/
/*--- Initialize address protocol ---*/
/*----------------------------------------------------*/
bzero((char*)&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(SERVERADDRESS);
server.sin_port = htons(PORT);
/*---------------------------------------------------*/
/*--- S E N D I N G D A T A --*/
/*---------------------------------------------------*/
printf("\nSend UDP data...\n\n");
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
clock_gettime(CLOCK_MONOTONIC_RAW, &loop_start);
frames_total = 0;
for (int i = 0; i < BUFFER_SIZE; i += UDP_FRAME) {
//while(1) {
if (sendto(sockfd, &buffer[i], UDP_FRAME, 0,
(const struct sockaddr*)&server, sizeof(server)) < 0)
{
fprintf(stderr, "Error in sendto()\n");
//return EXIT_FAILURE;
}
count_frame += 1;
clock_gettime(CLOCK_MONOTONIC_RAW, &loop_end);
if ((loop_end.tv_nsec - loop_start.tv_nsec) > 5000000) {
printf("\nCount [%d] ... ", n);
printf("Fames sent: %d\n", count_frame);
frames_total += count_frame;
n+=1;
count_frame = 0;
clock_gettime(CLOCK_MONOTONIC_RAW, &loop_start);
}
}
printf("Total successful counted frames: %d \n", frames_total);
return EXIT_SUCCESS;
}
sendto()
如果主机不知道到主机的 路由 会给你一个错误(几乎从来没有这种情况,因为你的主机会有默认网关)。否则,如果您的数据包未到达目标应用程序,您可能(或可能不会)收到 ICMP 目的地无法到达的消息,但这是不可靠的,并且不会通过调用 sendto()
.
进行通信
你可以做的是用
查询套接字
struct sock_extended_err err;
socklen_t errlen = sizeof(err);
getsockopt(fd, SOL_IP, IP_RECVERR, &err, &errlen);
对于收到的错误,这将为您提供有关套接字上收到的错误的详细信息(即 ICMP 端口无法访问,ICMP 主机无法访问等。pp)。这会有所帮助,但正如我所说,它是不可靠的,因为 ICMP 消息通常受到严格的速率限制,如果您的数据包被数据包过滤器(防火墙)阻止,则在途中被过滤或根本不发送。
UDP 是一种不可靠的协议。一旦数据包离开接口,对 sendto
的调用就成功了。之后,是否到达目的地取决于网络。
即使网络支持表明主机或端口不可访问的 ICMP 消息,在您的特定情况下也无关紧要,因为您要发送到多播地址。如果您至少有一个支持多播的接口,系统将选择一个接口来发送数据包。它可以被多个(或没有)主机接收。所以说目的地不可达是没有意义的。
我正在使用 C 中的 sendto()
函数。我已经设置了目标地址和目标端口。在发送 UDP 帧时,我可以在 Wireshark 中看到帧,并且 Wireshark 显示的数据包数量与我在程序中定义的完全相同。
问题是即使无法到达目标地址,帧仍在发送,我可以在 Wireshark 中看到它。
如果目标 IP 不存在,sendto()
函数不应该生成错误吗?
if (sendto(sockfd, &buffer[i], UDP_FRAME, 0,
(const struct sockaddr*)&server, sizeof(server)) < 0)
{
fprintf(stderr, "Error in sendto()\n");
//return EXIT_FAILURE;
}
目的地。 IP:234.168.0.1 目标端口:80 或 9(丢弃协议)
#define PORT (80)
#define FRAMES (20000)
#define UDP_FRAME (1442)
#define SERVERADDRESS "234.168.0.1"
#define BUFFER_SIZE (FRAMES * UDP_FRAME)
char buffer[BUFFER_SIZE];
int main(int argc, char **argv)
{
struct timespec start, end, loop_start, loop_end;
int sockfd, count_frame = 0, frames_total, i = UDP_FRAME, n=1;
struct sockaddr_in server;
printf("Build Data...\n");
build(buffer, sizeof(buffer));
printf("Configure socket...\n");
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
fprintf(stderr, "Error opening socket");
return EXIT_FAILURE;
}
/*----------------------------------------------------*/
/*--- Initialize address protocol ---*/
/*----------------------------------------------------*/
bzero((char*)&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(SERVERADDRESS);
server.sin_port = htons(PORT);
/*---------------------------------------------------*/
/*--- S E N D I N G D A T A --*/
/*---------------------------------------------------*/
printf("\nSend UDP data...\n\n");
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
clock_gettime(CLOCK_MONOTONIC_RAW, &loop_start);
frames_total = 0;
for (int i = 0; i < BUFFER_SIZE; i += UDP_FRAME) {
//while(1) {
if (sendto(sockfd, &buffer[i], UDP_FRAME, 0,
(const struct sockaddr*)&server, sizeof(server)) < 0)
{
fprintf(stderr, "Error in sendto()\n");
//return EXIT_FAILURE;
}
count_frame += 1;
clock_gettime(CLOCK_MONOTONIC_RAW, &loop_end);
if ((loop_end.tv_nsec - loop_start.tv_nsec) > 5000000) {
printf("\nCount [%d] ... ", n);
printf("Fames sent: %d\n", count_frame);
frames_total += count_frame;
n+=1;
count_frame = 0;
clock_gettime(CLOCK_MONOTONIC_RAW, &loop_start);
}
}
printf("Total successful counted frames: %d \n", frames_total);
return EXIT_SUCCESS;
}
sendto()
如果主机不知道到主机的 路由 会给你一个错误(几乎从来没有这种情况,因为你的主机会有默认网关)。否则,如果您的数据包未到达目标应用程序,您可能(或可能不会)收到 ICMP 目的地无法到达的消息,但这是不可靠的,并且不会通过调用 sendto()
.
你可以做的是用
查询套接字struct sock_extended_err err;
socklen_t errlen = sizeof(err);
getsockopt(fd, SOL_IP, IP_RECVERR, &err, &errlen);
对于收到的错误,这将为您提供有关套接字上收到的错误的详细信息(即 ICMP 端口无法访问,ICMP 主机无法访问等。pp)。这会有所帮助,但正如我所说,它是不可靠的,因为 ICMP 消息通常受到严格的速率限制,如果您的数据包被数据包过滤器(防火墙)阻止,则在途中被过滤或根本不发送。
UDP 是一种不可靠的协议。一旦数据包离开接口,对 sendto
的调用就成功了。之后,是否到达目的地取决于网络。
即使网络支持表明主机或端口不可访问的 ICMP 消息,在您的特定情况下也无关紧要,因为您要发送到多播地址。如果您至少有一个支持多播的接口,系统将选择一个接口来发送数据包。它可以被多个(或没有)主机接收。所以说目的地不可达是没有意义的。