Echo server: Difference between revisions

2,101 bytes added ,  15 years ago
C
(C)
Line 5:
 
The implementation must not stop responding to other clients if one client sends a partial line or stops reading responses.
 
=={{header|C}}==
{{works with|POSIX}}
 
This is a rather standard code (details apart); the reference guide for such a code is the [http://beej.us/guide/bgnet Beej's Guide to Network programming]. The dependency from POSIX is mainly in the use of the <tt>read</tt> and <tt>write</tt> functions, (using the socket as a file descriptor sometimes make things simpler).
 
<lang c>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
 
#define MAX_ENQUEUED 20
#define BUF_LEN 256
#define PORT_STR "12321"
 
void wait_for_zombie(int s)
{
while(waitpid(-1, NULL, WNOHANG) > 0) ;
}
 
int main()
{
struct addrinfo hints, *res;
struct sockaddr addr;
struct sigaction sa;
socklen_t addr_size;
int sock;
 
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
 
if ( getaddrinfo(NULL, PORT_STR, &hints, &res) != 0 ) {
perror("getaddrinfo");
exit(EXIT_FAILURE);
}
 
if ( (sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1 ) {
perror("socket");
exit(EXIT_FAILURE);
}
sa.sa_handler = wait_for_zombie;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if ( sigaction(SIGCHLD, &sa, NULL) == - 1 ) {
perror("sigaction");
exit(EXIT_FAILURE);
}
 
if ( bind(sock, res->ai_addr, res->ai_addrlen) == 0 ) {
freeaddrinfo(res);
if ( listen(sock, MAX_ENQUEUED) == 0 ) {
for(;;) {
addr_size = sizeof(addr);
int csock = accept(sock, &addr, &addr_size);
if ( csock == -1 ) {
perror("accept");
} else {
if ( fork() == 0 ) {
close(sock);
char buf[BUF_LEN];
int r;
while( (r = read(csock, buf, BUF_LEN)) > 0 ) {
(void)write(csock, buf, r);
}
exit(EXIT_SUCCESS);
}
close(csock);
}
}
} else {
perror("listen");
exit(EXIT_FAILURE);
}
} else {
perror("bind");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}</lang>
 
=={{header|Tcl}}==