Birlikte Geliştirelim: C İle TCP Client Yazımı

Birlikte Geliştirelim serisine hoşgeldiniz. Bu seride Kirpi Development Kirpi Development bünyesinde geliştirdiğimiz NeuroLink’in geliştirme sürecinde kendi deneyimlerimi ve öğrendiklerimi makale haline getirerek Türkçe kaynak oluşturacağım. İlk konumuz C ile tcp client ve server yazmak olacak.

Bu makaledeki test ortamı WSL (Windows Subsystem for Linux) kullanılarak hazırlandı. Bu serinin temeli olacak bu konuyu analttığım makalete tıklayarak uşabilirsiniz.

TCP Client Nasıl Yazılır?

Yazacağımız client sunucuya (bizim belirleyeceğimiz ip adresine) gidecek ve bizim belirlediğimiz port üzerinden sunucuya bir mesaj bırakacak.

İlk önce C kodunun tamamını vereceğim daha sonra açıklamalarını yapacağım:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
    int sock;
    struct sockaddr_in server_addr;
    char* message = "Merhaba, ...!";

    sock = socket(AF_INET, SOCK_STREAM, 0);

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
     if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) 
     {
        printf("Sunucuya bağlanılamadı.\n");
        return -1;
     }
     printf("Sunucuya bağlanıldı.\n");
    send(sock, message, strlen(message), 0);
    printf("Mesaj gönderildi: %s\n", message);
    close(sock);
    return 0;
}

Kütüphanelerle başalyalım:

#include <stdio.h> Standart Giriş/Çıkış. Ekrana printf ile yazı yazdırmak için kullanırız.
#include <string.h> Metin (karakter dizisi) işlemleri için. Kodumuzdaki strlen() (metnin uzunluğunu bulma) fonksiyonu buradan gelir.
#include <unistd.h> Linux sistem çağrılarıdır (UNIX Standard). Ağ bağlantısı bittiğinde soketi kapatan close() fonksiyonunu buradan alırız.
#include <arpa/inet.h> İşin asıl büyüsü buradadır. Ağ (Network) kütüphanesidir. İnternet adreslerini ve portları işletim sisteminin anlayacağı formata çevirir.

Değişkenler ve Struct (Yapılar) Mantığı:

int sock;
struct sockaddr_in server_addr;
char *message = "Merhaba...";
  • int sock; : Linux’ta her şey bir dosyadır. Ağ bağlantısı bile! Bir bağlantıyı açtığınızda Linux size bir “Dosya Kimlik Numarası” (File Descriptor) verir. İşte sock değişkeni bu numarayı aklında tutar.
  • struct sockaddr_in server_addr; : Struct, birden fazla değişkeni tek bir paket haline getirmektir. sockaddr_in Linux’un içinde hazır bulunan bir pakettir ve içine bağlanacağımız hedefin IP adresini, Portunu vs. koyarız.
  • char *message : C dilinde string (metin) diye bir değişken türü yoktur. Metinler aslında yanyana dizilmiş karakter (char) dizileridir. * işareti (pointer) bu dizinin bellekteki başlangıç adresini gösterir.

Hedefi Belirleme (Ağ Bayt Sırası – Big Endian):

sock = socket(AF_INET, SOCK_STREAM, 0);

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  • socket(AF_INET, SOCK_STREAM, 0): Burada Linux’a diyoruz ki; “Bana IPv4 (AF_INET) formatında ve TCP kesintisiz veri akışı (SOCK_STREAM) tipinde bir iletişim hattı aç.”
  • htons(8080): htons (Host TO Network Short) fonksiyonu tam olaraksizin bilgisayarınızın okuduğu 8080 sayısını, ağ kablosundan geçebilecek Big-Endian formatına çevirir.
  • inet_addr("127.0.0.1"): Yazdığımız metin tabanlı IP adresini, bilgisayarın anlayacağı 32-bitlik gerçek ağ adresine dönüştürür. 127.0.0.1 daima “kendi bilgisayarım” demektir (Localhost).

Harekete Geçme (Bağlan ve Gönder)

if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)

connect(...): İşletim sistemine “Hattı (sock) al, şu adrese (server_addr) git ve kapıyı çal” deriz. Eğer karşı tarafta bir Node.js sunucusu yoksa kapı açılmaz ve bu fonksiyon 0‘dan küçük bir hata değeri (örneğin -1) döndürür. Biz de if ile bunu yakalayıp ekrana “Bağlanılamadı” yazarız.

send(sock, message, strlen(message), 0);
close(sock);
  • send(...): Kapı açıldıysa bu komut çalışır. İşletim sistemine şunları veririz: Hangi hat üzerinden gidecek (sock), ne gönderecek (message), kaç harf gönderecek (strlen(message)).
  • close(sock): C dilinde çöp toplayıcı (Garbage Collector) yoktur. Açtığımız kapıyı kapatmazsak RAM’de sızıntı (Memory Leak) olur. Bu yüzden işimiz bitince hattı kapatıyoruz.

Ek Olarak

Bu kod parçasını çalıştırdığınızda WSL nizde henüz bir Noje.js bulunmadığı için sunucuya bağlanamadı hatasını alacaksınız.

Bu makalede C ile en verimli şekilde tcp client yazmayı gösterdim. Olabildiğince basitleştirerek açıklamaya çalıştım fakat makaleleri nasıl daha iyi bir hale getirebileceğim hakkında fikirleriniz varsa yorumlara yazabilir veya benle iletişim kurabilirsiniz. Ayrıca aklınıza takılan bölümleri yorumlarda sorabilirsiniz hepsine cevap vermeye çalışacağım.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir