gpt4 book ai didi

c - 来自 recvfrom 的错误

转载 作者:太空宇宙 更新时间:2023-11-04 07:58:50 27 4
gpt4 key购买 nike

我尝试创建一个函数,将 icmp 数据包发送到另一台计算机,当另一台计算机发回某些内容时,该函数返回 1,否则返回 0。但是 recvfrom 函数返回错误:“errno:资源暂时不可用”。我在 Mac OS X 上工作,所以我不包含来自 linux 内核的头文件。任何人都可以帮助我,因为我被困住了。

#include "info.h"


char *getip()
{
char buffer[256];
struct hostent *h;

gethostname(buffer, 256);
h = gethostbyname(buffer);

return inet_ntoa(*(struct in_addr *)h->h_addr);

}


int host_alive(char *dst_addr, char *src_addr)
{
struct ip *ippacket;
struct ip *ip_reply;
struct icmp *icmppacket;
struct sockaddr_in connection;
struct timeval tv;
char *packet;
char *buffer;
int optval;
int addrlen;
int size;
int sock = 0;

packet = malloc(sizeof(struct ip) + sizeof(struct icmp));
buffer = malloc(sizeof(struct ip) + sizeof(struct icmp));

check(getuid() == 0, "Root priviliges are needed. Try: sudo ./bin/main");

ippacket = (struct ip *) packet;
icmppacket = (struct icmp *) (packet + sizeof(struct ip));

ippacket->ip_hl = 5;
ippacket->ip_v = 4;
ippacket->ip_tos = 0;
ippacket->ip_len = sizeof(struct ip) + sizeof(struct icmp);
ippacket->ip_id = htons(random());
ippacket->ip_ttl = 255;
ippacket->ip_p = IPPROTO_ICMP;
inet_aton(src_addr, &ippacket->ip_src);
inet_aton(dst_addr, &ippacket->ip_dst);

tv.tv_sec = 5;
tv.tv_usec = 0;

check((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1,\
"Failed to create socket");

check(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(int)) != -1,\
"Failed to set the option to the socket.");
check(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(struct timeval)) != -1,\
"Failed to set the option to the socket.");

icmppacket->icmp_type = ICMP_ECHO;
icmppacket->icmp_code = 0;
icmppacket->icmp_id = 0;
icmppacket->icmp_seq = 0;
icmppacket->icmp_cksum = in_cksum((unsigned short *)icmppacket, sizeof(struct icmp));

ippacket->ip_sum = in_cksum((unsigned short *)ippacket, sizeof(struct ip));

connection.sin_family = AF_INET;
connection.sin_addr.s_addr = inet_addr(dst_addr);

sendto(sock, packet, ippacket->ip_len, 0, (struct sockaddr *)&connection,\
sizeof(struct sockaddr));

addrlen = sizeof(connection);
check((size = recvfrom(sock, buffer, sizeof(struct ip) + sizeof(struct icmp), 0,\
(struct sockaddr *)&connection, (socklen_t *)&addrlen)) != -1,\
"Failed to receive a message.");

printf("Received %d byte reply from %s:\n", size , dst_addr);
ip_reply = (struct ip*) buffer;
printf("ID: %d\n", ntohs(ip_reply->ip_id));
printf("TTL: %d\n", ip_reply->ip_ttl);

close(sock);

free(packet);
free(buffer);

return 1;

error:
if (sock)
close(sock);
free(packet);
free(buffer);
return 0;
}


unsigned short in_cksum(unsigned short *addr, int len)
{
int sum = 0;
u_short answer = 0;
u_short *w = addr;
int nleft = len;

while (nleft > 1) {
sum += *w++;
nleft -= 2;
}

if (nleft == 1) {
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}

最佳答案

根据 recvfrom 的文档,如果您使用非阻塞调用,这是预期的:

If no messages are available at the socket, the receive call waits for a message to arrive, unless the socket is nonblocking (see fcntl(2)) in which case the value -1 is returned and the external vari- able errno set to EAGAIN. The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested; this behavior is affected by the socket-level options SO_RCVLOWAT and SO_RCVTIMEO described in getsockopt(2).

如果您对什么值映射到什么错误感到好奇,您可以在 /usr/include/sys/errno.h 中查找 errno 值。

如果您希望此函数阻塞,您可能需要设置 MSG_WAITALL 标志,该标志“请求操作阻塞,直到满足完整请求”。

通常在低级 UNIX 套接字代码中,您会在该套接字上执行 select 以等待读取信号,然后调用 recvfrom 接收数据仅当该信号触发时。您也可以执行非阻塞接收,并在 EAGAIN 上等待一小段时间再重试,尽管这样效率较低。

关于c - 来自 recvfrom 的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48177104/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com