发送到:无效的参数

Posted

技术标签:

【中文标题】发送到:无效的参数【英文标题】:sendto: Invalid argument 【发布时间】:2014-03-14 20:25:07 【问题描述】:

我试图让一个程序(客户端)使用 C 中的套接字与另一个(服务器)通信,但我经常从服务器收到错误“无效参数”。

在解释发生的情况后,我将尝试展示与此问题相关的代码片段:

对于客户端,我假设一切正常:客户端向服务器发送请求,服务器正确接收消息,但是当服务器尝试回复时,我收到“无效参数”错误。

这是服务器主函数使用的变量的声明:

int port = DEFAULT_PORT;
int sock;
struct sockaddr_in hostAdress, clientAdress;
socklen_t clientAdressLength;

这里我将socket绑定到hostAdress:

sock = socket(PF_INET,SOCK_DGRAM,0);
memset(&hostAdress, 0, sizeof(struct sockaddr_in));
memset(&clientAdress, 0, sizeof(struct sockaddr_in));
hostAdress.sin_family = AF_INET;
hostAdress.sin_port = htons(port);
hostAdress.sin_addr.s_addr = INADDR_ANY;
bind(sock, (struct sockaddr*) &hostAdress, sizeof(hostAdress));

在一段代码之后,我进入一个循环接收信息,以这种方式使用recvfrom:

recvfrom(sock, dataBuffer, sizeof(dataBuffer), 0, (struct sockaddr*)&clientAdress, &clientAdressLength);

服务器收到请求后,识别并跳转到该函数(此行为已确认):

handle_helloRQ(sock, clientAdress, clientAdressLength);

虽然我知道可以通过 sizeof(clientAdress) 获得“clientAdressLength”,但不知何故这样做解决了我上次遇到的同样问题。 该函数声明为:

int handle_helloRQ(int sock, struct sockaddr_in server_addr, socklen_t server_addr_length)

在这个函数中,主要的变量是:

char buffer[512];
size_t bufferSize = sizeof(buffer);
memset(&buffer, 0, sizeof(buffer));
stshort(2, buffer);
strcat(buffer+2, "Hello World");

stshort 是一个简单的宏,它在缓冲区的前 2 个字节中放置一个 short int。这按预期工作。

完成后,它会尝试执行以下操作:

sendto(sock, buffer, bufferSize, 0, (struct sockaddr*)&server_addr, server_addr_length);

... 这就是事情出错的时候。 sendto 返回-1,使用perror("sendto"); 我得到一个“Invalid Argument”错误。 我尝试了一千种不同的方法来估算参数,但我找不到错误。遇到此类问题,我已经用尽了其他选择(即询问我大学的老师并将代码展示给一些更高级的同事),似乎没有人能够找到错误。 作为旁注,我确实使用

close(sock);

当服务器接收到要关闭的信号时,但我可能不得不强制关闭它一次,然后才能设法达到此功能。

感谢所有阅读本文的人,感谢您的宝贵时间!

【问题讨论】:

@HalimQarrum server_addr 在函数 handle_helloRQ 内部是 client_addr 你知道你使用的不是TCP也不是UDP套接字,而是IP套接字(协议0),所以绑定中的端口号无关紧要吗? @HalimQarroum 它被声明为char dataBuffer[4];。客户端发送的数据始终是char[4] @HalimQarroum 有可能,尽管它分布在很多文件中,并且简单地粘贴在这里会比较广泛。 【参考方案1】:

试试这个:

sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); // <-- add protocol
...    
clientAdressLength = sizeof(clientAdress); // <-- add this
recvfrom(sock, dataBuffer, sizeof(dataBuffer), 0, (struct sockaddr*)&clientAdress, &clientAdressLength);
...
handle_helloRQ(sock, (struct sockaddr*)&clientAdress, clientAdressLength); // <-- pass address by pointer
...
close(sock);

int handle_helloRQ(int sock, struct sockaddr* recip_addr, socklen_t recip_addr_length)

    char buffer[512];
    memset(&buffer, 0, sizeof(buffer));
    stshort(2, buffer);
    strcat(buffer+2, "Hello World");

    sendto(sock, buffer, sizeof(buffer), 0, recip_addr, recip_addr_length);
    ...

【讨论】:

应该没有任何区别,因为协议 0 请求该协议系列和类型的默认协议。对于 PF_INET 和 SOCK_DGRAM,这将是 UDP。 这可能是真的,但我也做了其他更改。每次调用recvfrom() 时都初始化clientAdressLength,并将客户端地址作为sockaddr* 而不是sockaddr_in 传递给handle_helloRQ(),因此recvfrom() 返回的长度对sendto() 有意义。 谢谢@RemyLebeau,它成功了。经过一番测试,我得出结论,要么是修改了socket()函数,要么是增加了clientAdressLength的初始化。 这个答案对我有帮助:在 recv 修复之前设置地址长度!

以上是关于发送到:无效的参数的主要内容,如果未能解决你的问题,请参考以下文章

如何将复杂的参数发送到 asp.net

数据中的Ajax传递参数发送到php

PyQt在连接到信号时将参数发送到插槽

将正确的 JSON 作为参数发送到 RPC

将二进制数据作为参数发送到 Web 服务中的方法?

将 C# 字符串作为参数发送到非托管 C++ DLL 函数