UDP sendto()错误:无效的参数
问题描述:
我们试图应用基于UDP的协议,并在sendto()函数中遇到了一些问题。UDP sendto()错误:无效的参数
当我们试图响应与ACK写入请求,我们得到“无效参数”从的sendto()函数
这是我们的代码:
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) perror("TTFTPERROR: bind() failed");
FD_ZERO(&fds);
FD_SET(sock, &fds);
timeout.tv_sec = WAIT_FOR_PACKET_TIMEOUT;
timeout.tv_usec = 0;
while (1) {
recvMsgSize = recvfrom(sock, &wrqBuffer, FULL_PACKET_SIZE, 0, (struct sockaddr *) &echoClntAddr, &cliAddrLen);
if (recvMsgSize > 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
行和recvfrom
上面几行的组合。
你正在做的是,你重复使用recvfrom
给你的sockaddr发送回复(在这种情况下为ACK)。这是绝对合法和正确的,你还可以通过无连接协议向其他人发送回复(你没有其他方式知道该向谁发送答案,也没有其他协议版本!)。
但是:当你正确提供&cliAddrLen
到recvfrom
,因此它可以返回已写入缓冲区echoClntAddr
实际地址长度(这可能会改变,想到的IPv4 VS IPv6地址),你再打sendto
与sizeof(echoClntAddr)
作为地址字段的大小。
由于echoClntAddr
很可能是sockaddr_storage
(它应该是,无论如何),它的大小将比任何有效协议的地址大小都大。因此,这是一个无效的论点。或者说,地址是。
您应该拨打sendto
与cliAddrLen
(并在致电recvfrom
之前初始化cliAddrLen
至sizeof(echoClntAddr)
)。
答
而且要非常小心,你通过有效的,现有的IP地址绑定()的参数: echoServAddr.sin_addr.s_addr
如果没有网络接口与IP恰好暴露解决绑定在某些平台上不会失败(例如ESP32),但sendto()肯定会失败。我花了2天时间来调试,我很生气!
什么是错误/错误代码? – Samer
22,错误是“无效参数” – user3350919
@szczurcio:这将是一个编译器错误,而不是运行时错误。但是我知道[sendto()'](http://pubs.opengroup.org/onlinepubs/009695399/functions/sendto.html)采用了'const void *'作为第二个参数。 –