2 ** server.c -- a stream socket server demo
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
14 #include <arpa/inet.h>
18 #define PORT "3490" // the port users will be connecting to
20 #define BACKLOG 10 // how many pending connections queue will hold
22 void sigchld_handler(int s
)
24 while(waitpid(-1, NULL
, WNOHANG
) > 0);
27 // get sockaddr, IPv4 or IPv6:
28 void *get_in_addr(struct sockaddr
*sa
)
30 if (sa
->sa_family
== AF_INET
) {
31 return &(((struct sockaddr_in
*)sa
)->sin_addr
);
34 return &(((struct sockaddr_in6
*)sa
)->sin6_addr
);
39 int sockfd
, new_fd
; // listen on sock_fd, new connection on new_fd
40 struct addrinfo hints
, *servinfo
, *p
;
41 struct sockaddr_storage their_addr
; // connector's address information
45 char s
[INET6_ADDRSTRLEN
];
48 memset(&hints
, 0, sizeof hints
);
49 hints
.ai_family
= AF_UNSPEC
;
50 hints
.ai_socktype
= SOCK_STREAM
;
51 hints
.ai_flags
= AI_PASSIVE
; // use my IP
53 if ((rv
= getaddrinfo(NULL
, PORT
, &hints
, &servinfo
)) != 0) {
54 fprintf(stderr
, "getaddrinfo: %s\n", gai_strerror(rv
));
58 // loop through all the results and bind to the first we can
59 for(p
= servinfo
; p
!= NULL
; p
= p
->ai_next
) {
60 if ((sockfd
= socket(p
->ai_family
, p
->ai_socktype
,
61 p
->ai_protocol
)) == -1) {
62 perror("server: socket");
66 if (setsockopt(sockfd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
,
72 if (bind(sockfd
, p
->ai_addr
, p
->ai_addrlen
) == -1) {
74 perror("server: bind");
82 fprintf(stderr
, "server: failed to bind\n");
86 freeaddrinfo(servinfo
); // all done with this structure
88 if (listen(sockfd
, BACKLOG
) == -1) {
93 sa
.sa_handler
= sigchld_handler
; // reap all dead processes
94 sigemptyset(&sa
.sa_mask
);
95 sa
.sa_flags
= SA_RESTART
;
96 if (sigaction(SIGCHLD
, &sa
, NULL
) == -1) {
101 printf("server: waiting for connections...\n");
103 while(1) { // main accept() loop
104 sin_size
= sizeof their_addr
;
105 new_fd
= accept(sockfd
, (struct sockaddr
*)&their_addr
, &sin_size
);
111 inet_ntop(their_addr
.ss_family
,
112 get_in_addr((struct sockaddr
*)&their_addr
),
114 printf("server: got connection from %s\n", s
);
116 if (!fork()) { // this is the child process
117 close(sockfd
); // child doesn't need the listener
119 if (recv(new_fd
, buf
, 99, 0) == -1) {
124 printf("server: recieved '%s'\n", buf
);
128 close(new_fd
); // parent doesn't need this