A C program that wishes to accept network connections (act as a "server") should first create a socket bound to the address "INADDR_ANY" and call listen
on it. Then, it can call accept
on the server socket to block until a client connects.
//Create the server socket
int servsock = socket(AF_INET, SOCK_STREAM, 0);
if(servsock < 0) perror("Failed to create a socket");
int enable = 1;
setsockopt(servsock, SOL_SOCKET, SO_REUSEADDR, (char*)&enable, sizeof(int));
//Bind to "any" address with a specific port to listen on that port
int port = 12345;
sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
if(bind(servsock, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
perror("Error binding to socket");
listen(servsock, 5);
//Accept a client
struct sockaddr_storage client_addr_info;
socklen_t len = sizeof client_addr_info;
int clientsock = accept(servsock, (struct sockaddr*)&client_addr_info, &len);
//Now you can call read, write, etc. on the client socket
The sockaddr_storage
struct that gets passed to accept
can be used to retrieve information about the client that connected. For example, here's how to determine the client's IP address:
char client_ip_str[INET6_ADDRSTRLEN + 1];
if(client_addr_info.ss_family == AF_INET) {
// Client has an IPv4 address
struct sockaddr_in *s = (struct sockaddr_in *)&client_addr_info;
inet_ntop(AF_INET, &s->sin_addr, client_ip_str, sizeof(client_ip_str));
} else { // AF_INET6
// Client has an IPv6 address
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&client_addr_info;
inet_ntop(AF_INET6, &s->sin6_addr, client_ip_str, sizeof(client_ip_str));
}