Echo server: Difference between revisions
Content added Content deleted
m (→{{header|Clojure}}: whitespace) |
(→{{header|C}}: Restructured code to be less obscure and less nested) |
||
Line 361: | Line 361: | ||
#define BUF_LEN 256 |
#define BUF_LEN 256 |
||
#define PORT_STR "12321" |
#define PORT_STR "12321" |
||
/* ------------------------------------------------------------ */ |
|||
/* How to clean up after dead child processes */ |
|||
/* ------------------------------------------------------------ */ |
|||
void wait_for_zombie(int s) |
void wait_for_zombie(int s) |
||
{ |
{ |
||
while(waitpid(-1, NULL, WNOHANG) > 0) ; |
while(waitpid(-1, NULL, WNOHANG) > 0) ; |
||
} |
} |
||
/* ------------------------------------------------------------ */ |
|||
/* Core of implementation of a child process */ |
|||
/* ------------------------------------------------------------ */ |
|||
void echo_lines(int csock) |
|||
{ |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
|||
/* ------------------------------------------------------------ */ |
|||
/* Core of implementation of the parent process */ |
|||
/* ------------------------------------------------------------ */ |
|||
void take_connections_forever(int ssock) |
|||
{ |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
/* Block until we take one connection to the server socket */ |
|||
⚫ | |||
/* If it was a successful connection, spawn a worker process to service it */ |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
|||
} |
|||
/* ------------------------------------------------------------ */ |
|||
/* The server process's one-off setup code */ |
|||
/* ------------------------------------------------------------ */ |
|||
int main() |
int main() |
||
{ |
{ |
||
struct addrinfo hints, *res; |
struct addrinfo hints, *res; |
||
⚫ | |||
struct sigaction sa; |
struct sigaction sa; |
||
socklen_t addr_size; |
|||
int sock; |
int sock; |
||
/* Look up the address to bind to */ |
|||
memset(&hints, 0, sizeof(struct addrinfo)); |
memset(&hints, 0, sizeof(struct addrinfo)); |
||
hints.ai_family = AF_UNSPEC; |
hints.ai_family = AF_UNSPEC; |
||
hints.ai_socktype = SOCK_STREAM; |
hints.ai_socktype = SOCK_STREAM; |
||
hints.ai_flags = AI_PASSIVE; |
hints.ai_flags = AI_PASSIVE; |
||
if ( getaddrinfo(NULL, PORT_STR, &hints, &res) != 0 ) { |
if ( getaddrinfo(NULL, PORT_STR, &hints, &res) != 0 ) { |
||
perror("getaddrinfo"); |
perror("getaddrinfo"); |
||
Line 385: | Line 432: | ||
} |
} |
||
/* Make a socket */ |
|||
if ( (sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1 ) { |
if ( (sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1 ) { |
||
perror("socket"); |
perror("socket"); |
||
Line 390: | Line 438: | ||
} |
} |
||
/* Arrange to clean up child processes (the workers) */ |
|||
sa.sa_handler = wait_for_zombie; |
sa.sa_handler = wait_for_zombie; |
||
sigemptyset(&sa.sa_mask); |
sigemptyset(&sa.sa_mask); |
||
sa.sa_flags = SA_RESTART; |
sa.sa_flags = SA_RESTART; |
||
if ( sigaction(SIGCHLD, &sa, NULL) == - |
if ( sigaction(SIGCHLD, &sa, NULL) == -1 ) { |
||
perror("sigaction"); |
perror("sigaction"); |
||
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
||
} |
} |
||
/* Associate the socket with its address */ |
|||
if ( bind(sock, res->ai_addr, res->ai_addrlen) |
if ( bind(sock, res->ai_addr, res->ai_addrlen) != 0 ) { |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
perror("accept"); |
|||
} else { |
|||
⚫ | |||
⚫ | |||
⚫ | |||
/* Echo loop */ |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
|||
⚫ | |||
/* State that we've opened a server socket and are listening for connections */ |
|||
⚫ | |||
⚫ | |||
⚫ | |||
perror("listen"); |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
||
} |
} |
||
⚫ | |||
take_connections_forever(sock); |
|||
return EXIT_SUCCESS; |
return EXIT_SUCCESS; |
||
}</lang> |
}</lang> |