Functions in the BSD socket interface operate on many different types of sockets, for example IPV4, IPV6, Unix sockets, etc but you're wondering why you have to CAST.
Well, frankly, because they screwed up on the interface. They should have made a union to allow clean casting. For example the sockaddr structure (the generic structure) can be any of the following:
Code:
struct sockaddr
struct sockaddr_in
struct sockaddr_storage
struct sockaddr_in6
struct sockaddr_un
struct sockaddr_dl
struct sockaddr_storage
And probably a few I missed. The correct way to have done this is within each structure, for example the sockaddr_in structure, should have been defined something like this:
Code:
struct correct_sockaddr_in
{
union
{
struct
{
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
struct sockaddr generic; /* shares the memory with the sin_family, sin_port, sin_addr */
};
};
This original interface was created back in 1982, so it's possible that C didn't support anonymous structures or unions at the time - but if it did, this is a major error in my opinion. Basically, the rule is, if you're using a BSD socket that takes a sockaddr, you can cast anything that is sockaddr_<anything> to sockaddr. Typically, I just use a C++/C wrapper around all the functions, so I don't have to worry about making casting errors, which I tend to do, a lot - when I've been away from the interface for any length of time.
On a modern compiler wrappers add little or no overhead, and almost always no overhead - so make use of them. Small functions are automatically inlined unless you specifically request absolutely no optimization, even in C - even if you're calling a statically linked library function. It's not 1982 anymore...
What's worse, is this interface is part of the POSIX standard, which means, basically, it's never going to go away, but at the same time, there's no reason not to have a better interface that exists on top of it, that does what I described. I've done it often enough. The IPV6 interface is 100% compatible with IPV4, so I recommend if you're doing any socket programing - use that. If you start working with IPV6, you're going to have to learn about zones (aka scopes) if your using what is called a "link local address". IPV6 is a little different, and in some ways, more work - but if you're using IPV4 address, it works pretty much the same.