CodeBlanks Logo Icon CodeBlanks

Birleştirme

  • C kursu
  • İleri seviye
  • Ders 83/83
  • 6 dk

Tüm katmanları birleştirerek çalışan bir mini sunucu yazarsın.

Birleştirme

Bu son derste server_run işlevini tanımlayacaksın. server_setup ile soket kurar, fork ile çocuk istemci oluşturur, çocuk connect ile bağlanır, ebeveyn accept ile kabul eder.

Bu, projenin tüm katmanlarını birleştirir: süreç (fork), soket (accept/connect) ve IPC (pipe'dan gelen desen). Main'de server_run() çağrılır ve printf("sunucu: %d\n", ok); yazdırılır. Tüm çıktı deterministiktir: "Proje hazır", "sayaç: 1", "soket: 1", "ipc: 1", "sunucu: 1". Mini sunucu çalışır halde elde edilir.

İstemci-sunucu akışı

server_run içinde: int sfd = server_setup();, pid_t pid = fork();. Çocuk: yeni soket oluştur, adresi doldur, connect(cfd, (struct sockaddr *)&addr, sizeof(addr)), close(cfd), _exit(0).

Ebeveyn: int cfd = accept(sfd, NULL, NULL);, close(cfd), close(sfd), wait(NULL), unlink("/tmp/cb_p.sock"), return cfd >= 0 ? 1 : 0;. accept bloklanır; çocuk connect yapana kadar bekler. Main'de server_setup'tan kalan sfd'yi kapatıp yolu silmeliyiz ki server_run içindeki server_setup temiz bir soket kurabilsin.

Uygulama server_run'ı ekle

int server_run(void) yaz: int sfd = server_setup();, pid_t pid = fork();, çocuksa 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);. Ebeveyn int cfd = accept(sfd, NULL, NULL); close(cfd); close(sfd); wait(NULL); unlink("/tmp/cb_p.sock"); return cfd >= 0 ? 1 : 0;. main'de server_setup sonrası close(sfd); unlink("/tmp/cb_p.sock"); ekle, sonra int ok = server_run(); ve printf("sunucu: %d\n", ok);.

Başlangıç kodu

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;
}

Örnek çözüm

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;
}

Beklenen çıktı

Proje hazır
sayaç: 1
soket: 1
ipc: 1
sunucu: 1

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Birleştirme adımlarını eşle

Kavram Anlamı
server_setup Soket kur
fork İstemci çocuk
connect İstemci bağlanır
accept Sunucu kabul eder

2 server_run ne yapar?

  • Yalnızca fork
  • Yalnızca printf
  • Soket kurup bağlantı kabul eder Doğru cevap
  • Hiçbir şey

Açıklama: server_run soket kurar, fork ile istemci açar ve accept eder.

3 accept çağrısı

Soru
int cfd = accept(sfd, ____, NULL);
Cevap
int cfd = accept(sfd, NULL, NULL);

Açıklama: accept'in ikinci parametresi NULL; adres istemiyoruz.

İleri seviye bölümündeki tüm dersler