This is to describe how to write networking programs in C using the BSD Socket Layer API. This mostly applies to almost all other languages with only minor modifications. This is an updated version of the page which is designed to be non-AddressFamily specific, for the old version see NetworkProgrammingOld. SocketAddressing may also be useful.
The various steps of setting up a server are:
getaddrinfo(3) will sort out the correct parameters for socket(2) and bind(2), making things fairly simple. An example below:
int bind_service(char *service,int socktype) {
struct addrinfo hints; struct addrinfo *result; struct addrinfo *result_iter; int serverfd;
hints.ai_flags=AI_PASSIVE; hints.ai_family=PF_UNSPEC; /* We don't care if it's PF_INET, or PF_INET6 / hints.ai_socktype=SOCK_STREAM / 0 for any type, SOCK_STREAM for streams, SOCK_DGRAM for datagrams / hints.ai_protocol=0; / 0 for any protocol, use getprotobyname(3) to find a protocol / hints.ai_addrlen=0; hints.ai_addr=NULL; hints.ai_canonname=NULL; / Unused */ hints.ai_next=NULL;
ret=getaddrinfo(NULL,service,&hints,&result); if (ret!=0) {
fprintf(stderr,"getaddrinfo failed: %s",gai_strerror(ret)); return -1;
}
for(result_iter = result;result_iter;result_iter=result_iter->next) {
serverfd = socket(result_iter->ai_family,result_iter->ai_socktype,result_iter->ai_protocol); if (serverfd<0) {
perror("socket"); continue;
} if (bind(serverfd,result_iter->address,result_iter->addrlen)<0) {
perror("bind"); continue;
} break;
}
if (!result_iter) {
fprintf(stderr,"Unable to bind to service \"%s\"\n",service); freeaddrinfo(result); return -1;
}
freeaddrinfo(result); return serverfd;
}
void do_client(int clientfd) {
char *message = "Hello World\n"; write(clientfd,message); close(clientfd);
}
int main(int argc,char **argv) {
int serverfd;
serverfd = bind_service("hello",SOCK_STREAM);
if (serverfd<0) {
return 1;
}
if (listen(serverfd,8)<0) {
perror("listen"); return 1;
}
for (;;) {
int clientfd;
clientfd = accept(serverfd);
if (clientfd<0) {
perror("accept"); /* Note that accept tends to fail reasonably often, so don't abort the server here */
}
if (fork()==0) {
/* Client Thread */ close(serverfd); do_client(clientfd); exit(0);
} else {
/* Server Thread */ close(clientfd);
}
}
close(serverfd);
}
A simple client implementation:
int create_client_connection(char *hostname,char *service) {
struct addrinfo hints; struct addrinfo result; struct addrinfo result_iter; int ret; int clientfd;
hints.ai_flags=0; hints.ai_family=PF_UNSPEC; hints.ai_socktype=SOCK_STREAM; hints.ai_protocol=0; hints.ai_addrlen=0; hints.ai_address=NULL; hints.ai_canonname=NULL;
ret=getaddrinfo(hostname,service,&hints,&result); if (ret!=0) {
fprintf("getaddrinfo failed: %s",gai_strerror(ret)); return -1;
}
for(result_iter = result; result ; result_iter=result_iter->next) {
clientfd=socket(result_iter->ai_family,result_iter->ai_socktype,result_iter->ai_protocol); if (clientfd<0) {
perror("socket"); continue;
} if (bind(clientfd,result_iter->ai_address,result_iter->ai_addrlen)<0) {
perror("bind"); close(clientfd); continue;
} break;
}
if (!result_iter) {
return -1;
}
return clientfd;
}
int main(int argc,char **argv) {
int clientfd; char buffer[65535?; int length;
clientfd=create_client_connection("localhost","hello");
if (clientfd<0) {
return 1;
}
len=read(clientfd,buffer,sizeof(buffer));
if (len<0) {
perror("read"); close(clientfd); return 1;
}
/* Write it to stdout (fd1) */ write(1,buffer,len);
close(clientfd);
}
2 pages link to NetworkProgramming: