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.
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.
Share Improve this question edited Feb 16 at 19:10 Mike asked Feb 16 at 18:45 MikeMike 8142 gold badges8 silver badges17 bronze badges 13 | Show 8 more comments1 Answer
Reset to default 1You 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.
sockaddr_in
is a structure, not a function. You don't call it... – Shawn Commented Feb 16 at 18:57void main()
and no error checking like your code is showing, I'd drop it like a hot potato in favor of something better. – Shawn Commented Feb 16 at 19:01bind
function should be well-documented in any decent book or tutorial. And the way to solve it should be known to anyone that has passed the beginners stage of learning C. – Some programmer dude Commented Feb 16 at 19:08struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = htons(8080) };
and maybe something like this afterwardsinet_pton(AF_INET, "0.0.0.0", &addr.sin_addr)
– Memos Electron Commented Feb 16 at 19:20(const struct sockaddr *)&addr
in the call tobind()
. This is normal -bind()
can accept many types of address. – pmacfarlane Commented Feb 16 at 20:45