I would like to create a sockaddr
struct without the funny casting because I have a function that will return sockaddr
structs. But I cannot really figure out how to re-pack the data from a sockaddr_in
to a sockaddr
. I am following this tutorial that shows this done like this
struct sockaddr_in myaddr;
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr);
I have a function to return regular sockaddr
sockaddr CreateAddress(std::string ip, uint16_t port){
sockaddr_in address = {0};
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(ip.c_str());
address.sin_port = htons(port);
// return as sockaddr instead..
sockaddr addr = {0};
addr.sa_len = sizeof(sockaddr);
addr.sa_family = AF_INET;
// how to fill in sockaddr.sa_data?
// maybe like this?
addr.sa_data[0] = (address.sin_port >> 8) & 0xFF;
addr.sa_data[1] = (address.sin_port) & 0xFF;
addr.sa_data[2] = (address.sin_addr.s_addr >> 24) & 0xFF;
addr.sa_data[3] = (address.sin_addr.s_addr >> 16) & 0xFF;
addr.sa_data[4] = (address.sin_addr.s_addr >> 8) & 0xFF;
addr.sa_data[5] = (address.sin_addr.s_addr) & 0xFF;
return addr;
}
The socket API functions are built to take a struct sockaddr *
as a parameter because there are multiple socket address types that it could accept, i.e. struct sockaddr_un
for UNIX domain sockets, struct sockaddr_in
for IPv4, struct sockaddr_in6
for IPv6, etc. The struct sockaddr
type is how the socket API (written in C) implements inheritance.
As such, these functions don't actually expect that a struct sockaddr *
parameter actually points to a struct of that type. Based on the socket type, it will internally cast it to the proper type.
This means that you should work with struct sockaddr_in
instead of struct sockaddr
and cast the address of these structs to struct sockaddr *
anytime you interact with a socket function. This is the expected way to use these functions.