Mike
Mike

Reputation: 814

Missing parameter in sockaddr_in initialization

I'm following an online tutorial for a [very] simple web server. It works, but the initialization of sockaddr_in() is missing a parameter. So I'm not sure why it does work and not sure what I should use for the missing parameter to make my IDE parser happy.

The program:

#include <sys/socket.h>
#include <string.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <unistd.h>
#include <netinet/in.h>

int main(void) {
    int s = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr = {
        AF_INET,
        0x901f, // the hex code for 8080 (little endian)
        0
    };

    bind(s, &addr, sizeof(addr));
    listen(s, 10);

    int client_fd = accept(s, 0, 0);

    char buffer[256] = {0};
    recv(client_fd, buffer, 256, 0);

    char* f = buffer + 5;
    *strchr(f, ' ') = 0;
    int opened_fd = open(f, O_RDONLY);
    sendfile(client_fd, opened_fd, 0, 256);
    close(opened_fd);
    close(client_fd);
    close(s);
    return 0;
}

The library definition:

/* Structure describing an Internet socket address.  */
struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port;         /* Port number.  */
    struct in_addr sin_addr;        /* Internet address.  */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr)
               - __SOCKADDR_COMMON_SIZE
               - sizeof (in_port_t)
               - sizeof (struct in_addr)];
  };

Compile errors:

$ gcc -o server server.c
server.c: In function ‘main’:
server.c:16:13: warning: passing argument 2 of ‘bind’ from incompatible pointer type [-Wincompatible-pointer-types]
   16 |     bind(s, &addr, sizeof(addr));
      |             ^~~~~
      |             |
      |             struct sockaddr_in *
In file included from server.c:1:
/usr/include/x86_64-linux-gnu/sys/socket.h:112:49: note: expected ‘const struct sockaddr *’ but argument is of type ‘struct sockaddr_in *’
  112 | extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
      |                                                 ^

EDIT: Added compile errors and fixed semantics.

Upvotes: 2

Views: 74

Answers (1)

Luis Colorado
Luis Colorado

Reputation: 12708

You wrote:

        AF_INET,
        0x901f, // the hex code for 8080 (little endian)
        0

It's better to use:

        .sin_family = AF_INET,
        .sin_port = htonh(8080), // in decimal :)
        .sin_addr = { .s_addr = INADDR_ANY },  // (a wildcard)

You don't need to change INADDR_ANY to network byte order as it is already in that format.

Also, the second parameter of bind(2) is required to be a struct sockaddr * so better if you cast your data, as in:

    int res = bind(s, (const struct sockaddr *)&addr, (socklen_t)sizeof(addr));

and, of course, check the returned value of bind() for errors.

Upvotes: 1

Related Questions