发送到错误:无效的参数
Posted
技术标签:
【中文标题】发送到错误:无效的参数【英文标题】:sendto error: Invalid argument 【发布时间】:2015-08-23 12:16:47 【问题描述】:我在套接字中使用sendto()
函数时遇到了麻烦
int main(int argc, const char * argv[])
int acceptFd;
struct sockaddr_in servaddr, cliaddr;
char recieveBuf[512];
char sendBuf[512];
socklen_t cliLen;
if(-1 == (acceptFd = socket(AF_INET,SOCK_DGRAM,0))) perror("socket() failed.\n");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6789);
if(-1==bind(acceptFd,(struct sockaddr*)&servaddr,sizeof(servaddr))) perror("bind() failed.\n");
bzero(&cliaddr, sizeof(cliaddr));
while(1)
if(recvfrom(acceptFd, recieveBuf, 512, 0, (struct sockaddr*) &cliaddr, &cliLen) == -1)
perror("recvfrom() failed");
continue;
strcpy(sendBuf,"recieved\n");
printf("%s\n",sendBuf);
if(-1 == sendto(acceptFd,sendBuf, 512,0,(struct sockaddr*)&cliaddr,cliLen))
perror("sendto() failed");
continue;
recvfrom()
工作正常,但每次调用 sendto()
时,错误处理都会打印出:sendto() failed: Invalid argument
发送程序在这里:
#include "test.AcceptMessage.pb.h"
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main(int argc, const char * argv[])
int sendSocket;
struct sockaddr_in cliaddr;
char buf[512];
if(-1 == (sendSocket = socket(AF_INET,SOCK_DGRAM,0))) perror("socket() failed.\n");
bzero(&cliaddr, sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
cliaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
cliaddr.sin_port = htons(6789);
sendto(sendSocket,buf, 512,0,(
struct sockaddr*)&cliaddr, sizeof(cliaddr));
recvfrom(sendSocket,buf,512,0, nullptr, nullptr);
printf("%s\n",buf);
return 0;
那么这段代码有什么问题呢?
【问题讨论】:
将调用 sendto(2) 中的 cliLen 更改为sizeof (struct sockaddr_in)
或 sizeof cliaddr
。可能系统调用自动检查使您传递给内核的参数大小无效。
【参考方案1】:
来自man recvfrom
:
在调用之前,它 [addrlen] 应该被初始化为 与 src_addr 关联的缓冲区。
因此,初始化您的 cliLen
变量:
socklen_t cliLen = sizeof(cliaddr);
【讨论】:
这确实有效,但我很想知道为什么:如果我已经知道 sockaddr 的长度,为什么还要麻烦以任何方式获取长度? 来自man recvfrom
:“如果提供的缓冲区太小,返回的地址将被截断;在这种情况下,addrlen
将返回一个大于提供给调用的值。”这意味着addrlen
表示潜在的缓冲区溢出。
非常感谢,看来我应该更仔细地阅读 API 文档了。
@reavenisadesk,不是。你不知道。您已将调用中的cliLen
更改为recvefrom
,因此您失去了价值。内核的系统调用接口期望将固定大小传递给内核,但是当从它返回时,您可以获得 struct sockaddr_in
结构中返回的大小的不同值,以允许您改进存储。如果你检查结构定义,你会发现结构上的填充(在从内核端返回时不考虑,但在系统调用参数检查中需要)
@LuisColorado 是的,cliLen 最初是 init,但每次调用 recvfrom 时都会更改,对吗?【参考方案2】:
你没有任何理由在这里使用recvfrom()
和sendto()
。这是一个连接的套接字。只需使用send()
和recv().
【讨论】:
以上是关于发送到错误:无效的参数的主要内容,如果未能解决你的问题,请参考以下文章