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
#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
#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ı
int cfd = accept(sfd, ____, NULL);
int cfd = accept(sfd, NULL, NULL);
Açıklama: accept'in ikinci parametresi NULL; adres istemiyoruz.