TCP sendto (C++) 在 Linux 上失败,但在 OSX 上失败。 Errno: EINVAL 22 无效参数

TCP sendto (C++) fails on Linux but not OSX. Errno: EINVAL 22 Invalid argument

在我的应用程序的客户端,以下 运行 在 OSX 上没问题。但是,当 Linux(Ubuntu 12 或 Raspbian)上的 compiled/run 时,sendto() 总是因 EINVAL/22/invalid 参数而失败。我如何在 Linux 上 运行?

std::vector<uint8_t> rawVect;
// rawVect.push_back()...a bunch of bytes

const uint8_t* sendBytes = &rawVect[0]; // or rawVect.data();  
size_t sendSize = rawVect.size();

if(sendSize > 0){

    long numBytes = sendto(control_fd, sendBytes, sendSize, 0, res->ai_addr, _res->ai_addrlen);
}

我怀疑 Linux 上的 C++ 11 库和 std::vectors。我的 makefile 看起来与此类似。

mac:  
g++ -std=c++0x myprogram.cpp 
# (w/ llvm libc++)

ubuntu:  
clang++-3.5 -g -std=c++11 -stdlib=libc++ myprogram.cpp  
# couldn't use g++ 4.8 or prior because it didn't support std::vector::insert as I was using it elsewhere. 4.9 not avail for Ubuntu 12.  

pi:  
g++-4.9 -std=c++0x myprogram.cpp  

没有足够的继续。添加打印语句以显示传递给 sendto 的所有参数的值。然后打印出res->ai_addr中投回sockaddr_in后的相关成员。

一个假设。假设 ipv4,ai_addrlen 的值应该正好等于 sizeof(struct sockaddr_in)。或者 sizeof(sockaddr_in6) 如果套接字是 ipv6。如果您传入的值大于该套接字类型预期的实际大小,则某些操作系统不会那么宽容。将 ai_addrlen 分配为 sizeof(sockaddr_storage).

就是这种情况

man 3 sendto 表示如果 "The dest_len argument is not a valid length for the address family" 可能会返回 EINVAL,也许尽管 connected-mode 套接字的地址参数被忽略了。鉴于您在标题中提到了 TCP,我假设 control_fd 是一个 connected-mode 套接字。尝试简单地使用 send(control_fd, sendBytes, sendSize, 0) 甚至 write(control_fd, sendBytes, SendSize) 代替。