1

Here is a sample socket programming snippet from the client side. My question revolves around the type-casting that casted sockaddr_in into sockaddr. My question is that why is that casting necessary there, what is going on there exactly?

#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define PORT 8080
int main ( int argument, char const *argv[] )
{
int obj_socket = 0, reader;
struct sockaddr_in serv_addr;
char *message = "A message from Client !";
char buffer[1024] = {0};
if (( obj_socket = socket (AF_INET, SOCK_STREAM, 0 )) < 0)
{
printf ( "Socket creation error !" );
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if(inet_pton ( AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf ( "\nInvalid address ! This IP Address is not supported !\n" );
return -1;
}
if ( connect( obj_socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr )) < 0) // <--- QUESTION ABOUT THIS LINE
{
Printf ( "Connection Failed : Can't establish a connection over this socket !" );
return -1;
}
send ( obj_socket , message , strlen(message) , 0 );
printf ( "\nClient : Message has been sent !\n" );
reader = read ( obj_socket, buffer, 1024 );
printf ( "%s\n",buffer );
return 0;
}

I've been reading the documentation and going throughout the header files to understand the structures however there is one last thing that I couldn't get.

The <sys/socket.h> header defines the sockaddr structure that includes at least the following members: sa_family_t sa_family address family char sa_data[] socket address (variable-length data)

The <netinet/in.h> header shall define the sockaddr_in structure, which shall include at least the following members: sa_family_t sin_family AF_INET. in_port_t sin_port Port number. struct in_addr sin_addr IP address.

My question is, at this line of the code:

if ( connect( obj_socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr )) < 0)

What is the purpose of this casting here which casted sockaddr_in to sockaddr. I understand that it is mandatory to cast here, but I would like to know why is it so? Thank you

  • 1
    The socket API is ancient and written in/for C. So, you will find some API decisions which are not anymore usual (especially not in C++). – Scheff's Cat Feb 15 '21 at 11:08
  • O.T.: The indentation is completely missing. I guess you're copy/pasting into a Smartphone. Additionally, I saw a `Printf` the compiler would probably complain about. ;-) – Scheff's Cat Feb 15 '21 at 11:11
  • I have specified the casting that I previously mentioned. I appreciate your concern. To be clear, when connnecting -- the code is casting sockaddr_in to sockaddr *. My question is why is this happening, what's the reason behind it? –  Feb 15 '21 at 11:12
  • 1
    This might address some of your doubts https://stackoverflow.com/a/42190913/4885321 – alagner Feb 15 '21 at 11:12
  • 2
    `connect` requires its second argument be a `struct sockaddr *`. A `&serv_addr` is `struct sockaddr_in *`. The socket api was crafted for passing in generic addresses and letting the socket configuration and address header info (which *is* in a sockaddr), along with the rest of the data known because of the third argument (the size). In short, it's the most dumbed-down non-inheritance-but-acts-like-it system you're apt to ever see, and casting is required, lest your compiler tell you the type is wrong. – WhozCraig Feb 15 '21 at 11:14
  • Related/Duplicate: [Why do we cast sockaddr_in to sockaddr when calling bind()?](https://stackoverflow.com/questions/21099041/) The same reason applies to connect(), too. – Remy Lebeau Feb 15 '21 at 20:28

1 Answers1

0

What is the purpose of this casting here which casted sockaddr_in to sockaddr.

sockaddr_in is not casted to sockaddr. sockaddr_in* is casted to sockaddr*.

That cast is done because the function connect which is being called doesn't accept a sockaddr_in* parameter, but a sockaddr*.


P.S. I recommend to not manually create a sockaddr_in, but instead to use getaddrinfo to create it.

P.P.S char *message = "A message from Client !"; is ill-formed in C++. The code that you've posted seems to be C rather than C++.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Thank you for your reply. This clears my doubts. For future readers, I am going to embed the connection function to this comment: ```int connect(int socket, const struct sockaddr *address, socklen_t address_len);``` –  Feb 15 '21 at 11:14