CodeBlanks Logo Icon CodeBlanks

Putting it together

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

main.c
#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

main.c
#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

Question
int cfd = accept(sfd, ____, NULL);
Answer
int cfd = accept(sfd, NULL, NULL);

Explanation: accept's second parameter is NULL; we don't want the address.

All lessons in Advanced