Skip to content

Instantly share code, notes, and snippets.

@arnetheduck
Created December 5, 2025 14:23
Show Gist options
  • Select an option

  • Save arnetheduck/052648f045473c39b91bc565ca40da24 to your computer and use it in GitHub Desktop.

Select an option

Save arnetheduck/052648f045473c39b91bc565ca40da24 to your computer and use it in GitHub Desktop.
Single socket, multiple threads
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#include <netdb.h>
#define PORT 2001
#define BACKLOG 128
#define THREAD_COUNT 3
typedef struct {
int listen_fd;
int id;
} thread_arg_t;
static void *accept_loop(void *argp) {
thread_arg_t *arg = (thread_arg_t*)argp;
int listen_fd = arg->listen_fd;
int tid = arg->id;
for (;;) {
struct sockaddr_storage ss;
socklen_t slen = sizeof ss;
int client_fd = accept(listen_fd, (struct sockaddr*)&ss, &slen);
if (client_fd < 0) {
if (errno == EINTR) continue;
perror("accept");
sleep(1);
continue;
}
char host[NI_MAXHOST], serv[NI_MAXSERV];
if (getnameinfo((struct sockaddr*)&ss, slen, host, sizeof host, serv, sizeof serv,
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
printf("Thread %d: accepted connection from %s:%s\n", tid, host, serv);
} else {
printf("Thread %d: accepted connection (fd=%d)\n", tid, client_fd);
}
close(client_fd); /* drop connection and accept next */
break;
}
return NULL;
}
int main(void) {
int listen_fd = socket(AF_INET6, SOCK_STREAM, 0);
if (listen_fd < 0) {
perror("socket");
return 1;
}
/* Allow both IPv4 and IPv6 (v6->v4 mapping) */
if (setsockopt(listen_fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof(int)) < 0) {
/* non-fatal on some systems */
}
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof addr);
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_port = htons(PORT);
if (bind(listen_fd, (struct sockaddr*)&addr, sizeof addr) < 0) {
perror("bind (need root for ports <1024?)");
close(listen_fd);
return 1;
}
if (listen(listen_fd, BACKLOG) < 0) {
perror("listen");
close(listen_fd);
return 1;
}
pthread_t threads[THREAD_COUNT];
thread_arg_t args[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; ++i) {
args[i].listen_fd = listen_fd;
args[i].id = i;
if (pthread_create(&threads[i], NULL, accept_loop, &args[i]) != 0) {
perror("pthread_create");
close(listen_fd);
return 1;
}
}
/* Main thread can wait or do other work; join threads to keep process alive */
for (int i = 0; i < THREAD_COUNT; ++i) {
pthread_join(threads[i], NULL);
}
close(listen_fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment