Putting it together
- C course
- Advanced
- Lesson 83/83
- 6 min
Combine all layers into a working mini server.
Putting it together
In this final lesson you'll define the server_run function. It sets up the socket with server_setup, forks a child client with fork, the child connects with connect, the parent accepts with accept.
This combines all project layers: process (fork), socket (accept/connect) and IPC (the pattern from pipe). In main you call server_run() and print printf("sunucu: %d\n", ok);. All output is deterministic: "Proje hazır", "sayaç: 1", "soket: 1", "ipc: 1", "sunucu: 1". The mini server is working.
Client-server flow
Inside server_run: int sfd = server_setup();, pid_t pid = fork();. Child: create a new socket, fill the address, connect(cfd, (struct sockaddr *)&addr, sizeof(addr)), close(cfd), _exit(0).
Parent: int cfd = accept(sfd, NULL, NULL);, close(cfd), close(sfd), wait(NULL), unlink("/tmp/cb_p.sock"), return cfd >= 0 ? 1 : 0;. accept blocks until the child calls connect. In main we must close the sfd from server_setup and remove the path so server_setup inside server_run can bind a fresh socket.
Practice Add server_run
Write int server_run(void): int sfd = server_setup();, pid_t pid = fork();, if child int cfd = socket(AF_UNIX, SOCK_STREAM, 0);, struct sockaddr_un addr;, memset(&addr, 0, sizeof(addr));, addr.sun_family = AF_UNIX;, strncpy(addr.sun_path, "/tmp/cb_p.sock", sizeof(addr.sun_path) - 1);, connect(cfd, (struct sockaddr *)&addr, sizeof(addr));, close(cfd); _exit(0);. Parent: int cfd = accept(sfd, NULL, NULL); close(cfd); close(sfd); wait(NULL); unlink("/tmp/cb_p.sock"); return cfd >= 0 ? 1 : 0;. In main after server_setup add close(sfd); unlink("/tmp/cb_p.sock");, then int ok = server_run(); and printf("sunucu: %d\n", ok);.
Starter code
#include <stdio.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int worker_init(void);
int server_setup(void);
int ipc_setup(void);
int worker_count = 0;
pthread_mutex_t worker_lock = PTHREAD_MUTEX_INITIALIZER;
void *worker_fn(void *arg) {
(void)arg;
pthread_mutex_lock(&worker_lock);
worker_count++;
pthread_mutex_unlock(&worker_lock);
return NULL;
}
int worker_init(void) {
pthread_t t;
pthread_create(&t, NULL, worker_fn, NULL);
pthread_join(t, NULL);
return 1;
}
int server_setup(void) {
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, "/tmp/cb_p.sock", sizeof(addr.sun_path) - 1);
unlink("/tmp/cb_p.sock");
bind(fd, (struct sockaddr *)&addr, sizeof(addr));
listen(fd, 1);
return fd;
}
int ipc_setup(void) {
int p[2];
pipe(p);
pid_t pid = fork();
if (pid == 0) {
close(p[0]);
write(p[1], "ipc", 3);
close(p[1]);
_exit(0);
}
close(p[1]);
char buf[8] = {0};
int n = read(p[0], buf, 3);
close(p[0]);
wait(NULL);
return n > 0 ? 1 : 0;
}
// server_run fonksiyonunu yaz: server_setup + fork istemci (connect) + accept
int main(void) {
printf("Proje hazır\n");
worker_init();
printf("sayaç: %d\n", worker_count);
int sfd = server_setup();
printf("soket: %d\n", sfd >= 0 ? 1 : 0);
int r = ipc_setup();
printf("ipc: %d\n", r);
// server_run çağır ve "sunucu: 1" yazdır
return 0;
}Sample solution
#include <stdio.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int worker_init(void);
int server_setup(void);
int ipc_setup(void);
int server_run(void);
int worker_count = 0;
pthread_mutex_t worker_lock = PTHREAD_MUTEX_INITIALIZER;
void *worker_fn(void *arg) {
(void)arg;
pthread_mutex_lock(&worker_lock);
worker_count++;
pthread_mutex_unlock(&worker_lock);
return NULL;
}
int worker_init(void) {
pthread_t t;
pthread_create(&t, NULL, worker_fn, NULL);
pthread_join(t, NULL);
return 1;
}
int server_setup(void) {
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, "/tmp/cb_p.sock", sizeof(addr.sun_path) - 1);
unlink("/tmp/cb_p.sock");
bind(fd, (struct sockaddr *)&addr, sizeof(addr));
listen(fd, 1);
return fd;
}
int ipc_setup(void) {
int p[2];
pipe(p);
pid_t pid = fork();
if (pid == 0) {
close(p[0]);
write(p[1], "ipc", 3);
close(p[1]);
_exit(0);
}
close(p[1]);
char buf[8] = {0};
int n = read(p[0], buf, 3);
close(p[0]);
wait(NULL);
return n > 0 ? 1 : 0;
}
int server_run(void) {
int sfd = server_setup();
pid_t pid = fork();
if (pid == 0) {
int cfd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, "/tmp/cb_p.sock", sizeof(addr.sun_path) - 1);
connect(cfd, (struct sockaddr *)&addr, sizeof(addr));
close(cfd);
_exit(0);
}
int cfd = accept(sfd, NULL, NULL);
close(cfd);
close(sfd);
wait(NULL);
unlink("/tmp/cb_p.sock");
return cfd >= 0 ? 1 : 0;
}
int main(void) {
printf("Proje hazır\n");
worker_init();
printf("sayaç: %d\n", worker_count);
int sfd = server_setup();
printf("soket: %d\n", sfd >= 0 ? 1 : 0);
close(sfd);
unlink("/tmp/cb_p.sock");
int r = ipc_setup();
printf("ipc: %d\n", r);
int ok = server_run();
printf("sunucu: %d\n", ok);
return 0;
}Expected output
Proje hazır sayaç: 1 soket: 1 ipc: 1 sunucu: 1
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Match integration steps
| Term | Meaning |
|---|---|
server_setup |
Set up socket |
fork |
Client child |
connect |
Client connects |
accept |
Server accepts |
2 What does server_run do?
- Only fork
- Only printf
- Sets up socket and accepts a connection Correct answer
- Nothing
Explanation: server_run sets up the socket, forks a client and accepts.
3 accept call
int cfd = accept(sfd, ____, NULL);
int cfd = accept(sfd, NULL, NULL);
Explanation: accept's second parameter is NULL; we don't want the address.