TCP Chat over a Local Network
Minimal TCP Echo Server (C)
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define PORT 7000
int main(void) {
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0) {
perror("socket");
return 1;
}
int opt = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
struct sockaddr_in srv;
memset(&srv, 0, sizeof(srv));
srv.sin_family = AF_INET;
srv.sin_addr.s_addr = htonl(INADDR_ANY);
srv.sin_port = htons(PORT);
if (bind(listen_fd, (struct sockaddr *)&srv, sizeof(srv)) < 0) {
perror("bind");
return 1;
}
if (listen(listen_fd, 20) < 0) {
perror("listen");
return 1;
}
struct sockaddr_in cli;
socklen_t cli_len = sizeof(cli);
int conn_fd = accept(listen_fd, (struct sockaddr *)&cli, &cli_len);
if (conn_fd < 0) {
perror("accept");
return 1;
}
char buf[1024];
for (;;) {
ssize_t n = recv(conn_fd, buf, sizeof(buf), 0);
if (n <= 0) break;
if (n == 5 && memcmp(buf, "exit\n", 5) == 0) break;
fwrite(buf, 1, n, stdout);
send(conn_fd, buf, n, 0);
}
close(conn_fd);
close(listen_fd);
return 0;
}
Minimal TCP Client (C)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 7000
#define BUFSZ 1024
int main(void) {
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
return 1;
}
struct sockaddr_in srv;
memset(&srv, 0, sizeof(srv));
srv.sin_family = AF_INET;
srv.sin_port = htons(PORT);
srv.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(fd, (struct sockaddr *)&srv, sizeof(srv)) < 0) {
perror("connect");
return 1;
}
char sendbuf[BUFSZ];
char recvbuf[BUFSZ];
while (fgets(sendbuf, sizeof(sendbuf), stdin)) {
send(fd, sendbuf, strlen(sendbuf), 0);
if (strcmp(sendbuf, "exit\n") == 0) break;
ssize_t n = recv(fd, recvbuf, sizeof(recvbuf) - 1, 0);
if (n <= 0) break;
recvbuf[n] = '\0';
fputs(recvbuf, stdout);
}
close(fd);
return 0;
}
Bidirectional Asynchronous Chat with select
TCP Server with Non-blocking Console and Socket (C)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define PORT 7000
int main(void) {
int srv_fd = socket(AF_INET, SOCK_STREAM, 0);
if (srv_fd < 0) { perror("socket"); return 1; }
int yes = 1;
setsockopt(srv_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = htonl(INADDR_ANY);
sa.sin_port = htons(PORT);
if (bind(srv_fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("bind"); return 1; }
if (listen(srv_fd, 20) < 0) { perror("listen"); return 1; }
struct sockaddr_in ca; socklen_t ca_len = sizeof(ca);
int cli_fd = accept(srv_fd, (struct sockaddr *)&ca, &ca_len);
if (cli_fd < 0) { perror("accept"); return 1; }
for (;;) {
fd_set rs; FD_ZERO(&rs);
FD_SET(STDIN_FILENO, &rs);
FD_SET(cli_fd, &rs);
int hi = cli_fd > STDIN_FILENO ? cli_fd : STDIN_FILENO;
struct timeval to = {5, 0};
int rc = select(hi + 1, &rs, NULL, NULL, &to);
if (rc < 0) { perror("select"); break; }
if (rc == 0) continue;
if (FD_ISSET(cli_fd, &rs)) {
char b[1024];
ssize_t n = recv(cli_fd, b, sizeof(b) - 1, 0);
if (n <= 0) break;
b[n] = '\0';
if (strcmp(b, "exit\n") == 0) break;
fputs(b, stdout);
}
if (FD_ISSET(STDIN_FILENO, &rs)) {
char line[1024];
if (!fgets(line, sizeof(line), stdin)) break;
send(cli_fd, line, strlen(line), 0);
}
}
close(cli_fd);
close(srv_fd);
return 0;
}
TCP Client with select (C)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 7000
#define BUFSZ 1024
int main(void) {
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) { perror("socket"); return 1; }
struct sockaddr_in sa; memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET; sa.sin_port = htons(PORT);
sa.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("connect"); return 1; }
for (;;) {
fd_set rs; FD_ZERO(&rs);
FD_SET(STDIN_FILENO, &rs); FD_SET(fd, &rs);
int hi = fd > STDIN_FILENO ? fd : STDIN_FILENO;
struct timeval to = {5, 0};
int rc = select(hi + 1, &rs, NULL, NULL, &to);
if (rc < 0) { perror("select"); break; }
if (rc == 0) continue;
if (FD_ISSET(fd, &rs)) {
char r[BUFSZ]; ssize_t n = recv(fd, r, sizeof(r) - 1, 0);
if (n <= 0) break; r[n] = '\0'; fputs(r, stdout);
}
if (FD_ISSET(STDIN_FILENO, &rs)) {
char s[BUFSZ]; if (!fgets(s, sizeof(s), stdin)) break;
send(fd, s, strlen(s), 0);
}
}
close(fd);
return 0;
}
Broadcast Chat to a Fixed Number of Clients
Server acepting two clients and boradcasting console input (C++)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <thread>
#include <vector>
#define PORT 7000
static int listen_fd;
static int clients[2] = {-1, -1};
static int ccount = 0;
void accept_one() {
struct sockaddr_in ca; socklen_t cl = sizeof(ca);
int fd = accept(listen_fd, (struct sockaddr *)&ca, &cl);
if (fd < 0) { perror("accept"); exit(1); }
if (ccount < 2) clients[ccount++] = fd;
}
int main() {
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
int yes = 1; setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
sockaddr_in sa{}; sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = htons(PORT);
if (bind(listen_fd, (sockaddr *)&sa, sizeof(sa)) < 0) { perror("bind"); return 1; }
if (listen(listen_fd, 8) < 0) { perror("listen"); return 1; }
std::thread t1(accept_one);
std::thread t2(accept_one);
t1.join(); t2.join();
for (;;) {
fd_set rs; FD_ZERO(&rs); FD_SET(STDIN_FILENO, &rs);
int hi = STDIN_FILENO;
for (int i = 0; i < ccount; ++i) {
if (clients[i] >= 0) { FD_SET(clients[i], &rs); if (clients[i] > hi) hi = clients[i]; }
}
struct timeval to{5,0};
int rc = select(hi + 1, &rs, NULL, NULL, &to);
if (rc <= 0) continue;
for (int i = 0; i < ccount; ++i) {
if (clients[i] >= 0 && FD_ISSET(clients[i], &rs)) {
char b[1024]; ssize_t n = recv(clients[i], b, sizeof(b) - 1, 0);
if (n <= 0) { close(clients[i]); clients[i] = -1; }
else { b[n] = '\0'; std::cout << b; }
}
}
if (FD_ISSET(STDIN_FILENO, &rs)) {
char line[1024]; if (!fgets(line, sizeof(line), stdin)) break;
for (int i = 0; i < ccount; ++i) if (clients[i] >= 0) send(clients[i], line, strlen(line), 0);
}
}
for (int i = 0; i < ccount; ++i) if (clients[i] >= 0) close(clients[i]);
close(listen_fd);
return 0;
}
Matching Client (C)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 7000
#define BUFSZ 1024
int main(void) {
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sa; memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET; sa.sin_port = htons(PORT); sa.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("connect"); return 1; }
for (;;) {
fd_set rs; FD_ZERO(&rs); FD_SET(STDIN_FILENO, &rs); FD_SET(fd, &rs);
int hi = fd > STDIN_FILENO ? fd : STDIN_FILENO;
struct timeval to = {5, 0};
int rc = select(hi + 1, &rs, NULL, NULL, &to); if (rc <= 0) continue;
if (FD_ISSET(fd, &rs)) {
char r[BUFSZ]; ssize_t n = recv(fd, r, sizeof(r) - 1, 0);
if (n <= 0) break; r[n] = '\0'; fputs(r, stdout);
}
if (FD_ISSET(STDIN_FILENO, &rs)) {
char s[BUFSZ]; if (!fgets(s, sizeof(s), stdin)) break; send(fd, s, strlen(s), 0);
}
}
close(fd);
return 0;
}
Scaalble Broadcast Server (unbounded clients) using select
Server (C++)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#define PORT 7000
int main() {
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
int yes = 1; setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
sockaddr_in sa{}; sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = htons(PORT);
if (bind(listen_fd, (sockaddr *)&sa, sizeof(sa)) < 0) { perror("bind"); return 1; }
if (listen(listen_fd, 64) < 0) { perror("listen"); return 1; }
std::vector<int> peers;
for (;;) {
fd_set rs; FD_ZERO(&rs);
FD_SET(listen_fd, &rs); FD_SET(STDIN_FILENO, &rs);
int hi = std::max(listen_fd, STDIN_FILENO);
for (int fd : peers) { FD_SET(fd, &rs); if (fd > hi) hi = fd; }
struct timeval to{2, 0};
int rc = select(hi + 1, &rs, NULL, NULL, &to);
if (rc < 0) { perror("select"); break; }
if (rc == 0) continue;
if (FD_ISSET(listen_fd, &rs)) {
sockaddr_in ca{}; socklen_t cl = sizeof(ca);
int cfd = accept(listen_fd, (sockaddr *)&ca, &cl);
if (cfd >= 0) peers.push_back(cfd);
}
if (FD_ISSET(STDIN_FILENO, &rs)) {
char line[1024]; if (fgets(line, sizeof(line), stdin)) {
for (int fd : peers) send(fd, line, strlen(line), 0);
}
}
for (size_t i = 0; i < peers.size(); ) {
int fd = peers[i];
if (FD_ISSET(fd, &rs)) {
char b[1024]; ssize_t n = recv(fd, b, sizeof(b) - 1, 0);
if (n <= 0) { close(fd); peers.erase(peers.begin() + i); continue; }
b[n] = '\0'; std::cout << b; // server displays client messages
}
++i;
}
}
for (int fd : peers) close(fd);
close(listen_fd);
return 0;
}
Client (C)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 7000
#define BUFSZ 1024
int main(void) {
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sa; memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET; sa.sin_port = htons(PORT); sa.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("connect"); return 1; }
for (;;) {
fd_set rs; FD_ZERO(&rs); FD_SET(STDIN_FILENO, &rs); FD_SET(fd, &rs);
int hi = fd > STDIN_FILENO ? fd : STDIN_FILENO;
struct timeval to = {5, 0};
int rc = select(hi + 1, &rs, NULL, NULL, &to); if (rc <= 0) continue;
if (FD_ISSET(fd, &rs)) {
char r[BUFSZ]; ssize_t n = recv(fd, r, sizeof(r) - 1, 0);
if (n <= 0) break; r[n] = '\0'; fputs(r, stdout);
}
if (FD_ISSET(STDIN_FILENO, &rs)) {
char s[BUFSZ]; if (!fgets(s, sizeof(s), stdin)) break; send(fd, s, strlen(s), 0);
}
}
close(fd);
return 0;
}
UDP Echo
UDP Server (C)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 8888
#define BUFSZ 256
int main(void) {
int s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) { perror("socket"); return 1; }
struct sockaddr_in sa; memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET; sa.sin_port = htons(PORT); sa.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("bind"); return 1; }
for (;;) {
char buf[BUFSZ];
struct sockaddr_in ca; socklen_t cl = sizeof(ca);
ssize_t n = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&ca, &cl);
if (n < 0) continue;
fwrite(buf, 1, n, stdout);
sendto(s, buf, n, 0, (struct sockaddr *)&ca, cl);
}
}
UDP Client (C)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 8888
#define BUFSZ 256
int main(int argc, char **argv) {
if (argc != 2) { fprintf(stderr, "usage: %s <server-ip>\n", argv[0]); return 1; }
int s = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in sa; memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET; sa.sin_port = htons(PORT);
if (inet_pton(AF_INET, argv[1], &sa.sin_addr) != 1) { perror("inet_pton"); return 1; }
char line[BUFSZ];
for (;;) {
if (!fgets(line, sizeof(line), stdin)) break;
sendto(s, line, strlen(line), 0, (struct sockaddr *)&sa, sizeof(sa));
char r[BUFSZ]; socklen_t sl = sizeof(sa);
ssize_t n = recvfrom(s, r, sizeof(r) - 1, 0, (struct sockaddr *)&sa, &sl);
if (n > 0) { r[n] = '\0'; fputs(r, stdout); }
}
close(s);
return 0;
}
Process and System Utilities
Get Current PID and Parenet PID (C)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
printf("pid=%d ppid=%d\n", (int)getpid(), (int)getppid());
return 0;
}
Invoke a Shell Command with system (C)
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int rc = system("uname -a");
printf("system() returned %d\n", rc);
return 0;
}
Timers
Periodic timer via setitimer + SIGALRM (C)
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
static volatile int ticks = 0;
static void on_alarm(int sig) {
(void)sig;
printf("tick %d\n", ++ticks);
}
int main(void) {
struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = on_alarm;
sigaction(SIGALRM, &sa, NULL);
struct itimerval iv; memset(&iv, 0, sizeof(iv));
iv.it_value.tv_sec = 1; // first fire
iv.it_interval.tv_sec = 1; // interval
setitimer(ITIMER_REAL, &iv, NULL);
for (;;) pause();
}
Sleep in milliseconds using select timeout (C)
#include <sys/select.h>
static void sleep_ms(unsigned int ms) {
struct timeval tv;
tv.tv_sec = ms / 1000;
tv.tv_usec = (ms % 1000) * 1000;
select(0, NULL, NULL, NULL, &tv);
}
select Basics
Wait for stdin with timeout (C)
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <unistd.h>
int main(void) {
for (;;) {
fd_set rs; FD_ZERO(&rs); FD_SET(STDIN_FILENO, &rs);
struct timeval to = {5, 0};
int rc = select(STDIN_FILENO + 1, &rs, NULL, NULL, &to);
if (rc < 0) { perror("select"); break; }
if (rc == 0) { puts("timeout"); continue; }
if (FD_ISSET(STDIN_FILENO, &rs)) {
char line[1024];
if (!fgets(line, sizeof(line), stdin)) break;
fputs(line, stdout);
}
}
return 0;
}
POSIX Threads
Create a thread and pass an argument (C)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct { int value; } args_t;
static void *worker(void *p) {
args_t *a = (args_t *)p;
printf("worker: value=%d\n", a->value);
return NULL;
}
int main(void) {
pthread_t th;
args_t a = { .value = 42 };
if (pthread_create(&th, NULL, worker, &a) != 0) {
perror("pthread_create");
return 1;
}
printf("main thread\n");
pthread_join(th, NULL);
return 0;
}
Network Interface Info
Read MAC from sysfs and IP via ioctl (C)
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
static int read_mac_sysfs(const char *ifname, char mac[18]) {
char path[256]; snprintf(path, sizeof(path), "/sys/class/net/%s/address", ifname);
FILE *f = fopen(path, "r"); if (!f) return -1;
size_t n = fread(mac, 1, 17, f); mac[(n < 17) ? n : 17] = '\0'; fclose(f);
return 0;
}
static int get_ip_ioctl(const char *ifname, struct in_addr *ip) {
int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) return -1;
struct ifreq ifr; memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { close(s); return -1; }
*ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
close(s); return 0;
}
int main(int argc, char **argv) {
if (argc != 2) { fprintf(stderr, "usage: %s <iface>\n", argv[0]); return 1; }
char mac[18] = {0};
if (read_mac_sysfs(argv[1], mac) == 0) printf("MAC: %s\n", mac);
struct in_addr ip; if (get_ip_ioctl(argv[1], &ip) == 0) printf("IP : %s\n", inet_ntoa(ip));
return 0;
}
Processes and fork
Basic fork example (C)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
pid_t p = fork();
if (p < 0) {
perror("fork");
} else if (p == 0) {
printf("child: pid=%d ppid=%d\n", (int)getpid(), (int)getppid());
} else {
printf("parent: pid=%d child=%d\n", (int)getpid(), (int)p);
}
return 0;
}
Concurrent TCP Server using fork (C)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define PORT 6000
#define BUFSZ 2048
static void reap(int) { while (waitpid(-1, NULL, WNOHANG) > 0) {} }
int main(void) {
signal(SIGCHLD, reap);
int lf = socket(AF_INET, SOCK_STREAM, 0);
int yes = 1; setsockopt(lf, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
struct sockaddr_in sa; memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = htons(PORT);
if (bind(lf, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("bind"); return 1; }
if (listen(lf, 64) < 0) { perror("listen"); return 1; }
for (;;) {
struct sockaddr_in ca; socklen_t cl = sizeof(ca);
int c = accept(lf, (struct sockaddr *)&ca, &cl);
if (c < 0) { perror("accept"); continue; }
pid_t pid = fork();
if (pid < 0) { perror("fork"); close(c); continue; }
if (pid == 0) { // child
close(lf);
char b[BUFSZ];
for (;;) {
ssize_t n = read(c, b, sizeof(b) - 1);
if (n <= 0) break;
b[n] = '\0';
printf("%s", b);
}
close(c);
_exit(0);
} else {
close(c);
}
}
}
Simple TCP Client to the forked server (C)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 6000
#define BUFSZ 2048
int main(int argc, char **argv) {
if (argc != 2) { fprintf(stderr, "usage: %s <server-ip>\n", argv[0]); return 1; }
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sa; memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET; sa.sin_port = htons(PORT);
if (inet_pton(AF_INET, argv[1], &sa.sin_addr) != 1) { perror("inet_pton"); return 1; }
if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("connect"); return 1; }
char line[BUFSZ];
while (fgets(line, sizeof(line), stdin)) write(fd, line, strlen(line));
close(fd);
return 0;
}