UDP sendto()错误:参数无效

我们正在尝试应用基于UDP的协议,并且在sendto()函数中存在一些问题。

当我们尝试用ack响应写请求时,我们从sendto()函数得到“invalid argument”

这是我们的代码:

int sock; // Socket sockaddr_in_t echoServAddr; // Local address sockaddr_in_t echoClntAddr; // Client address unsigned int cliAddrLen; // Length of incoming message data_packet_t echoBuffer; wrq_packet_t wrqBuffer; unsigned short echoServPort; // Server port int recvMsgSize; // Size of received message ack_packet_t Ack; struct timeval timeout; fd_set fds; /* Create socket for sending/receiving datagrams */ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) perror("TTFTPERROR: socket() failed"); /* Construct local address structure */ memset(&echoServAddr, 0, sizeof(echoServAddr)); echoServAddr.sin_family = AF_INET; echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); echoServAddr.sin_port = htons(echoServPort); /*Bind to the local address */ if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr))  0) break; // we got something! } Ack = CreateAckPacket(0); // send ack 0 if (sendto(sock, &Ack, sizeof(Ack), 0, (struct sockaddr *) &echoClntAddr, sizeof(echoClntAddr)) == -1){ perror("TTFTPERROR: sendto() failed to send ack 0"); exit(-1); } 

你能帮我们理解什么是错的吗?

可能的错误是sendto行和上面几行的sendto的组合。

你正在做的是,你重复使用recvfrom给你发送回复的sockaddr(在这种情况下为ACK)。 这绝对是合法和正确的,你怎么能在无连接协议上向某人发送回复(你没有其他方式知道发送答案的人,也没有协议版本!)。

但是:当你正确地提供&cliAddrLenrecvfrom ,它可以返回写入缓冲区echoClntAddr的实际地址长度(可能会有所不同,想想IPv4与IPv6地址),稍后你会调用sendto ,其大小为sizeof(echoClntAddr) ,大小为地址字段。
由于echoClntAddr很可能是sockaddr_storage (它应该是,无论如何),它的大小将大于任何有效协议的地址大小。 因此,这是一个无效的论点。 或者更确切地说,地址是。

您应该使用cliAddrLen调用sendto (并在调用recvfrom之前将sizeof(echoClntAddr)初始化为sizeof(echoClntAddr) )。

您还要非常小心地将VALID和EXISTING IP地址传递给bind()的参数:echoServAddr.sin_addr.s_addr

如果您没有使用该IP地址公开网络接口,则绑定在某些平台上不会失败(例如ESP32)但是sendto()肯定会失败。 我花了2天时间调试,我很生气!