0

On the client side of my application, the following runs fine on OSX. But when compiled/run on Linux (Ubuntu 12 or Raspbian) sendto() always fails with a EINVAL/22/invalid argument. How do I run it on 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);
}

I suspect C++ 11 libraries and std::vectors on Linux. My makefile looks similar to this.

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  
cloudsurfin
  • 2,467
  • 2
  • 25
  • 29
  • 2
    [man 3 sendto](http://linux.die.net/man/3/sendto) says that `EINVAL` may be returned if "The `dest_len` argument is not a valid length for the address family", perhaps despite the fact that the address argument is ignored for connected-mode sockets. Given that you mention TCP in the title, I assume that `control_fd` is a connected-mode socket. Try simply using `send(control_fd, sendBytes, sendSize, 0)` or even `write(control_fd, sendBytes, SendSize)` instead. – Casey Mar 06 '15 at 22:25
  • 1
    What @Casey said. If you pass more than 64KB -28 bytes to sendto, it should fail since you can't send that much into a UDP datagram. – selbie Mar 06 '15 at 22:26
  • Thanks @Casey. That was it. Not sure how I got to sendto in the first place. Much obliged. I'll give you an answer if you copy it over. – cloudsurfin Mar 06 '15 at 22:55

2 Answers2

1

man 3 sendto says that EINVAL may be returned if "The dest_len argument is not a valid length for the address family", perhaps despite the fact that the address argument is ignored for connected-mode sockets. Given that you mention TCP in the title, I assume that control_fd is a connected-mode socket. Try simply using send(control_fd, sendBytes, sendSize, 0) or even write(control_fd, sendBytes, SendSize) instead.

Casey
  • 41,449
  • 7
  • 95
  • 125
0

There's not enough to go on. Add print statements to reveal the values of all the parameters passed to sendto. Then print out the relevant members of res->ai_addr after casting back to sockaddr_in.

One hypothesis. The value of ai_addrlen should exactly equal sizeof(struct sockaddr_in) assuming ipv4. Or sizeof(sockaddr_in6) if the socket is ipv6. Some operating systems are less forgiving if you pass in a value that's bigger than the actual size expected for that socket type. Such would be the case with assigning the ai_addrlen to be sizeof(sockaddr_storage).

selbie
  • 100,020
  • 15
  • 103
  • 173