C++ Socket Programlama Örnekleri ile internet programcılığına adım atın! Sayfamızda yer alan örnekler sayesinde socket programlamayı kolayca öğrenebilirsiniz Hemen ziyaret edin!

Bu makalede, C++ programlama dilinde Socket Programlama temelleri anlatılmakta ve server-client sistemlerinin nasıl kurulacağı öğretilmektedir. Server-client mimarisinde, bir server (sunucu) ve bir veya daha fazla client (istemci) arasında veri alışverişi gerçekleştirilir. Bu makalede, bu alışverişin nasıl yapıldığına dair örnekler ve kodlar sunulmaktadır.
Socket programlama, özellikle ağ üzerinde veri alışverişinde sıklıkla kullanılan bir yöntemdir. Bu nedenle, bu konuda uzman olmak her programlama dilinde faydalıdır. Bu makale, özellikle C++ dili üzerinde Socket Programlama çalışmalarına başlayacak kişilere yardımcı olmayı amaçlamaktadır. Daha önce C++ ile yazılım geliştirmemiş olsanız bile, bu makale size yol gösterecektir.
Socket Programlama Nedir?
Socket programlama, ağ üzerinde veri alışverişinde bulunabilmenizi sağlayan bir programlama yöntemidir. Bir ağ bağlantısı üzerinde bir sunucu ve bir istemciden oluşur. Sunucu, diğer bağlantılar tarafından gelen istekleri dinler ve cevap verir. İstemci ise sunucu ile bağlantı kurarak isteklerini sunucuya gönderebilir ve sunucudan gelen cevapları alabilir.
Bu makale, socket programlama temellerini anlatmak ve nasıl uygulanacağını öğrenmek isteyenlere yardımcı olmak amacıyla hazırlanmıştır. Server-client sistemleri kurarak socket programlama ile veri alışverişinde bulunmanın nasıl gerçekleştirileceğine dair örnekler sunmaktadır. Ayrıca paket yapısı, parametreler ve fonksiyonlar gibi konulara da yer vermektedir.
Server - Client Sistem Kurulumu
Socket programlamada, server ve client sistemleri oluşturmak için belli adımlar izlenmelidir. Öncelikle server sistemi için, bir socket oluşturulmalı ve gerekli ayarlamalar yapılmalıdır. Socket oluşturma işlemi, AF_INET ve SOCK_STREAM parametreleri kullanılarak gerçekleştirilir. Ardından, server sistemi client talep ettiği sürece bağlantı bekler.
Client sistemi için ise, server ile bağlantı kurmak için gerekli ayarlamalar yapılmalıdır. Bunlar arasında, server adresi ve port numarası belirtilerek socket oluşturulması yer alır. Daha sonra, oluşturulan socket ile server'a bağlantı kurulur.
Server ve client sistemleri arasındaki iletişim için, paket yapısı kullanılır. Bu yapıda, her paket için bir header ve bir data bölümü yer alır. Header bölümünde paketin boyutu, tipi ve diğer bilgiler yer alırken, data bölümü ise paketin taşıdığı verileri içerir.
Bu işlemler tamamlandıktan sonra, server ve client sistemleri arasında veri gönderimi ve alımı gerçekleştirilebilir. Bunun için, send() ve recv() gibi fonksiyonlar kullanılabilir.
Bu adımların tamamı gerçekleştirildikten sonra, C++ socket programlama kullanarak çeşitli uygulamalar gerçekleştirilebilir. Örnekler arasında, basit chat uygulaması ve dosya transferi uygulaması yer alır.
Server Sistemi Kurulumu
Server sistemi kurulumu için, öncelikle bir socket oluşturulması gerekmektedir. Bu işlem için, socket fonksiyonu kullanılır. Socket fonksiyonu, yeni bir soket oluşturmak için kullanılan bir fonksiyondur. İlk parametre, soketin türünü belirtirken, ikinci parametre ise soketin türünün belirtilmesi için kullanılır.
Socket'in oluşturulmasının ardından, bir adres yapısı ve port numarası atanması gerekmektedir. Bunun için, addrinfo yapısı kullanılır. Bu yapı, sockaddr_in yapısına benzer bir yapıdır ve soket bilgileri ile birlikte adres yapısını da saklar. Port numarası belirtilirken, htons fonksiyonu kullanılarak önce byte order düzeltmesi yapılması gerekmektedir.
Bir sonraki adım, bağlantı beklemek için listen fonksiyonunun çağrılmasıdır. Listen fonksiyonu, soketin belirlenen portuna ve adresine gelen istekleri dinlemek için kullanılır. Bu fonksiyon, bağlantı bekleme kuyruğunu belirler.
Server sisteminin, gelen bağlantı taleplerine cevap verebilmesi için accept fonksiyonu kullanılması gerekmektedir. Bu fonksiyon, gelen bağlantıları beklemek için kullanılır ve bağlantı isteğini kabul ederek, yeni bir soket oluşturur.
// Socket oluşturmaint sock = socket(AF_INET, SOCK_STREAM, 0); |
// Adres yapısı oluşturmastruct addrinfo hints, *res;memset(&hints, 0, sizeof hints);hints.ai_family = AF_UNSPEC;hints.ai_socktype = SOCK_STREAM;getaddrinfo(NULL, "1234", &hints, &res); |
// Port numarası ve byte order düzeltmesiint port = 1234;uint16_t port_nb = htons(port); |
// Listen fonksiyonu ile bağlantı beklemelisten(sock, BACKLOG); |
// Accept fonksiyonu ile yeni bağlantı oluşturmastruct sockaddr_storage their_addr;socklen_t addr_size;int new_fd = accept(sock, (struct sockaddr *)&their_addr, &addr_size); |
Socket Oluşturma
Bir socket oluşturmak için öncelikle bir soket tanımlayıcısı (socket descriptor) oluşturulması gerekmektedir. Bu soket tanımlayıcısı, açılacak soket işlemlerinde kullanılacaktır. Socket tanımlayıcısının oluşturulması için socket() fonksiyonu kullanılır.
Socket() fonksiyonu, bir soket oluşturarak bir soket tanımlayıcısı döndürür. Bu fonksiyon, parametre olarak soketin ait olacağı ağ tipi, soketin türü ve kullanılacak protokol numarasını alır.
Soket türleri, örneğin SOCK_STREAM (TCP protokolü) veya SOCK_DGRAM (UDP protokolü) gibi network protokolüne göre değişir. Aynı zamanda, ağ tipi de belirtilmelidir. Örneğin, ağ tipi AF_INET (IPv4) veya AF_INET6 (IPv6) gibi.
Parametre | Açıklama |
---|---|
domain | Soketin ait olacağı ağ tipi |
type | Soketin türü |
protocol | Kullanılacak protokol numarası |
Örneğin, bir TCP soket oluşturmak için aşağıdaki gibi bir kod kullanılabilir:
int soketTanımlayıcısı = socket(AF_INET, SOCK_STREAM, 0);
Bu örnekte, soketin ait olduğu ağ tipi AF_INET (IPv4), soket türü SOCK_STREAM (TCP) ve kullanılacak herhangi bir protokol numarası belirtilmiştir.
Soketin gerekli ayarlamaları yapılana kadar, herhangi bir işlem yapılması mümkün değildir. Ayarlamalar yapıldıktan sonra bind() fonksiyonu ile sokete bir adres atanması gerekmektedir. Bu adresteki port numarası üzerinden soket iletişimi gerçekleştirilecektir.
Bağlantı Bekleme
Server sistemi oluşturulduktan sonra client taleplerini karşılamak için bağlantı beklemesi gerekmektedir. Bağlantı beklemek için "listen" fonksiyonu kullanılır.
Bu fonksiyon, belirtilen soketin bağlantı için hazır olduğunu bildirir ve gelen bağlantıları kabul eder. Belirtilen soketin bağlantılara kapalı hale gelmesi için "close" fonksiyonu kullanılır.
Aşağıda, listen fonksiyonunun kullanımına ilişkin bir örnek gibi bir kod parçası bulunmaktadır:
Kod | Açıklama |
---|---|
if (listen(sockfd, 5) == -1) { | Bağlantı beklemeye başlamak için "listen" fonksiyonu kullanılır. Belirtilen soket aynı anda en fazla 5 bağlantı talebini kabul edebilir. |
Yukarıdaki örnekte, "sockfd" değişkeni, dinlemek için oluşturulan soketin dosya tanımlayıcısını belirtmektedir. Eğer listen fonksiyonu hata verirse, perror fonksiyonu hata mesajını stderr çıktısına yazdırır ve programı sonlandırır.
Bağlantı beklediği süre boyunca server, gelen istekleri kabul edebilir veya reddedebilir. Kabul edildiği takdirde, kabul edilen bağlantı için ayrı bir soket yaratılır ve bu soket üzerinden client ile veri iletişimi sağlanır.
Client Sistemi Kurulumu
Client sisteminin kurulumu, server sisteminin kurulumu kadar önemlidir. Client sisteminin doğru bir şekilde oluşturulması, server ile rahat bir şekilde iletişim kurulmasını sağlar. Client sistemi kurulumu için öncelikle bilgisayarımızda bir IDE kurmadan önce, WinSock kütüphanesinin indirilip yüklendiğinden emin olmalıyız. WinSock kütüphanesi, Windows işletim sistemleri için TCP/IP protokolünü uygulayan bir socket arayüzüdür.
Client sistemi için gerekli kodların oluşturulması, aşağıdaki adımlarla gerçekleştirilebilir:
- Adım 1: Kullanılacak kütüphaneler tanımlanır (#include <iostream> gibi).
- Adım 2: WinSock kütüphanesine ait başlık dosyası tanımlanır (#include <winsock2.h>).
- Adım 3: Belirli port numarası ve IP adresi kullanarak bir socket oluşturulur (socket(AF_INET, SOCK_STREAM, 0)).
- Adım 4: Sunucunun IP adresi ve port numarası tanımlanır.
- Adım 5: Sunucu ile bağlantı kurulur (connect(socket, (SOCKADDR*)&addr, sizeof(addr))).
Yukarıdaki adımları takip ederek, client sisteminizin doğru bir şekilde oluşturulması sağlanır. Ayrıca, client sistemindeki sorunları ve hataları izlemek ve gidermek için, hata ayıklama işlemleri yapılabilir. Bunun için, WSAGetLastError() işlevi kullanılabilir.
Bu adımları takip ederek C++ ile socket programlama yapmak artık daha kolay! Hem server hem de client sistemleri için gereken temel adımları öğrendikten sonra, farklı uygulamalar ve proje örnekleri de deneyebilirsiniz.
Server ile Bağlantı Kurma
Client sisteminin server ile iletişim kurması için öncelikle, server sisteminin IP adresi ve port numarası bilinmelidir. Bu bilgilere erişmek için, client sisteminde kullanılacak olan socket adresi tanımlanmalıdır.
Bunun için, sockaddr_in struct yapısı kullanılır ve socket adresi, aşağıdaki gibi tanımlanır:
Alan | Değer |
sin_family | AF_INET |
sin_port | Server sisteminin kullanacağı porta göre belirlenir |
sin_addr | Server sisteminin IP adresi |
Socket adresi belirlendikten sonra, client sistemi soket oluşturma işlemi gerçekleştirir ve connect fonksiyonu kullanarak, server ile bağlantı kurar. Connect fonksiyonu çağrıldığında, client sistemi belirlenen IP adresi ve porta sahip bir server bulması ve bağlantı kurması için bekler.
Bağlantı kurulduktan sonra, client ve server arasında veri alışverişi gerçekleşebilir. Bu işlemlerin nasıl yapıldığı, önceki başlıklarda açıklanmaktadır.
Paket Yapısı
Paket Yapısı
Socket programlamanın temel amacı, server ve client sistemleri arasında veri alışverişi yapmaktır. Bu alışveriş sırasında, gönderilen her bir veri paketi belirli bir yapının içinde yer alır. Bu yapılara, paket yapısı denir.
Bir paket genellikle, başlık ve veri bölümlerinden oluşur. Başlık bölümü, paketin özelliklerini belirtirken, veri bölümü ise paket içinde taşınan verileri ifade eder. Paket yapısı, server ve client arasında belirli bir standarta uygun olarak sağlanmalıdır.
Paket yapısı için gerekli olan bazı parametreler, şunlardır:
- Paket Boyutu: Paketin boyutu, başlık ve veri bölümlerinin toplam boyutudur. Bu boyut, belirli bir limitin altında tutulmalıdır.
- Veri Tipi: Paket içinde taşınacak verilerin türü belirtilmelidir. Örneğin, bir mesaj göndermek isteniyorsa, bu mesajın karakter dizisi mi yoksa sayısal bir değer mi olduğu belirtilmelidir.
- Paket Kimlikleri: Paketin özelliklerini belirtmek için bir kimlik numarası ve/veya bir işlem kodu kullanılır. Böylece, alınan paketin ne işe yaradığı kolayca anlaşılabilir.
- Parity Bit: Veri bölümünün hatalı olup olmadığını kontrol etmek için kullanılan bir bit. Parity bit, genellikle veri bölümünde yer alan bitlerin toplamına göre hesaplanır.
Paket yapısı, server ve client sistemlerinin birbirleriyle doğru şekilde iletişim kurabilmesi için oldukça önemlidir. Eğer paket yapısı, belirli bir standartta sağlanmazsa, veri alışverişi sırasında hatalar oluşabilir ve sistemler istenilen şekilde çalışmayabilir.
Gönderme ve Alım
Socket programlama, server ve client sistemleri arasındaki veri alışverişini sağlamak için kullanılır. Gönderme ve alım işlemleri de bu amaçla gerçekleştirilir. Server sisteminden gönderilen veriler, client sistemine gönderilir ve vice versa. Bu işlemler için kullanılan bazı önemli fonksiyonlar şunlardır:
- send(): Bu fonksiyon, belirtilen bir soketten veri gönderir. Fonksiyon, verinin boyutunu, kaç byte'lık kısım gönderildiğini ve sonucu döndürür.
- recv(): Bu fonksiyon, belirtilen bir soketten veri alır. Fonksiyon, verinin boyutunu, kaç byte'lık kısım alındığını ve sonucu döndürür.
- htons(): Host byte order'ın network byte order'a dönüştürülmesi için kullanılır.
- inet_addr(): IP adreslerinin network byte order olarak dönüştürülmesi için kullanılır.
Send() fonksiyonu ile gönderilen veri, recv() fonksiyonu ile karşı tarafta alınır. Bu işlemler için belirli bir anlaşma yapılması gerekmektedir. Veriler sıralı bir şekilde gönderilir ve alınır. Ayrıca, veri alımı engellenebilir, bu nedenle recv() fonksiyonu bloklu bir şekilde kullanılmalıdır.
Bu işlemlerde TCP veya UDP soketleri kullanabilirsiniz. TCP soketleri, güvenilir bir veri alışverişi sağlar ve verili bir işlem yapar. UDP soketleri ise hızlı bir şekilde veri alışverişi yapar ve güvenilir değildir.
Gönderme ve alım işlemleri, socket programlamada önemli bir role sahiptir. Bu işlemleri doğru kullanmak, server-client sistemlerinin başarılı bir şekilde çalışmasını sağlayacaktır.
Uygulamalar
C++ socket programlama kullanarak, birçok farklı uygulama gerçekleştirilebilir. Bu bölümde, örneklerle birlikte C++ socket programlamayı kullanarak hangi uygulamaların gerçekleştirilebileceği açıklanmaktadır.
İlk örnek, basit bir chat uygulamasıdır. Bu uygulama, kullanıcıların aynı ağ üzerinde birbirleriyle yazışmalarına olanak tanır. Server sistemi, gelen bağlantı isteklerini kabul eder ve gelen mesajları tüm client'lara yansıtır.
Bir diğer uygulama ise dosya transferi uygulamasıdır. Client sistemi, seçtiği bir dosyayı server'a gönderir ve server sistemi de bu dosyayı kabul eder ve kaydeder. Bu uygulama, özellikle büyük dosyaların transferi için kullanışlıdır.
Bunların yanı sıra, C++ socket programlama ile birçok farklı uygulama gerçekleştirmek mümkündür. Örneğin, online oyunlar, veri tabanı işlemleri gibi birçok uygulama socket programlama kullanarak kolayca gerçekleştirilebilir. Socket programlama sayesinde, ağ üzerinden veri alışverişini hızlı ve güvenli bir şekilde gerçekleştirebilirsiniz.
Basit Chat Uygulaması
Server ve client sistemleri arasında gerçekleştirilebilecek uygulamalardan biri de chat uygulamalarıdır. Bu örnek uygulamada, clientlar servera bağlanarak mesajlaşabileceklerdir.
Bu basit chat uygulaması, öncelikle server tarafında bir socket oluşturarak başlar. Ardından clientlar, serverın IP adresi ve port numarasını kullanarak servera bağlanırlar. Bağlantı başarılı olduktan sonra, clientlar servera mesaj gönderebilirler ve bu mesajlar diğer clientlar tarafından da görülebilir.
Bu uygulama için gerekli olan kod örnekleri, server ve client için ayrı ayrı verilir. Ayrıca, kullanılan socket fonksiyonları ve mesaj gönderme/alma işlemleri de açıklanır. Öncelikle server tarafı kodları aşağıdaki gibidir:
Kod | Açıklama |
---|---|
serverSocket = socket(AF_INET, SOCK_STREAM, 0); | Server tarafında bir socket oluşturma işlemi gerçekleştirilir. |
serverAddress.sin_family = AF_INET; | Server adresinin kullanılacak internet protokolünü tanımlama işlemi yapılır. |
serverAddress.sin_port = htons(PORT); | Serverın kullanacağı port numarası atanır. |
serverAddress.sin_addr.s_addr = INADDR_ANY; | Serverın herhangi bir ağ arabirimini kullanabilmesi için INADDR_ANY seçeneği kullanılır. |
bind(serverSocket, (struct sockaddr*) &serverAddress, sizeof(serverAddress)); | Server socketi ile adres bilgisi arasında bağlantı kurulur. |
listen(serverSocket, 5); | Bağlantı taleplerinin dinlenmesi için listen() fonksiyonu kullanılır. |
Bu kodların ardından, server clientların bağlantı taleplerini kabul eder ve accept()
fonksiyonu çalıştırılır. Client tarafında ise, öncelikle servera bağlanmak için connect()
fonksiyonu kullanılır. Bağlantı başarılı olduktan sonra, client servera mesaj gönderebilir ve bu mesaj diğer clientlar tarafından da görülebilir.
Bu örnek uygulama, C++ socket programlama temellerinin anlaşılması için oldukça faydalıdır. Ayrıca, server-client uygulamalarının nasıl geliştirilebileceği konusunda da fikir verir.
Dosya Transferi Uygulaması
Server ve client sistemleri arasında dosya transferi yapmak, socket programlama ile oldukça kolaydır. İşlem için öncelikle server tarafında, dosyaların gönderileceği bir dizin oluşturulmalıdır. Client tarafında ise, gönderilecek olan dosyaların kaydedileceği bir dizin belirtilmelidir.
Dosya transferi için kullanılabilecek örnek kodlar şu şekildedir;
Server Kodu | Client Kodu |
---|---|
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 9002 int main(){ int sockfd, connfd, len; struct sockaddr_in servaddr, cli; sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd == -1){ printf("Socket creation failed!\n"); exit(0); } printf("Socket created successfully!\n"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0){ printf("Socket bind failed!\n"); exit(0); } printf("Socket bind successful!\n"); if(listen(sockfd, 5) < 0){ printf("Listen failed!\n"); exit(0); } printf("Server is listening...\n"); len = sizeof(cli); connfd = accept(sockfd, (struct sockaddr*)&cli, &len); if (connfd < 0){ printf("Server accept failed!\n"); exit(0); } printf("Server accepted client...\n"); close(sockfd); data(connfd); } void data(int sockfd){ char buffer[1024]; char fname[50]; int size; read(sockfd,fname,50); FILE *fp = fopen(fname,"rb"); if(fp==NULL){ printf("File open error\n"); return; } bzero(buffer,1024); int64_t file_size; fseek(fp, 0, SEEK_END); file_size = ftell(fp); rewind(fp); write(sockfd, (const char*)&file_size, sizeof(int64_t)); int64_t remain_data = file_size; size_t n; while (((n = fread(buffer, sizeof(char), 1024, fp)) > 0) && remain_data > 0){ write(sockfd, buffer, n); remain_data -= n; bzero(buffer, 1024); } fclose(fp); } | #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 9002 int main(){ int sockfd, connfd; struct sockaddr_in servaddr, cli; sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd == -1){ printf("Socket creation failed!\n"); exit(0); } printf("Socket created successfully!\n"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); servaddr.sin_port = htons(PORT); if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0){ printf("Server connection failed!\n"); exit(0); } printf("Connected to the server successfully!\n"); data(sockfd); } void data(int sockfd){ char buffer[1024]; char fname[50]; int64_t file_size; printf("Enter the filename: "); scanf("%s",fname); write(sockfd, fname, sizeof(fname)); read(sockfd,&file_size,sizeof(int64_t)); FILE *fp = fopen(fname,"wb"); if(fp==NULL){ printf("File creation error\n"); return; } int remain_data = file_size; while((remain_data > 0) && ((fread(buffer,sizeof(char),1024,sockfd))>0)){ fwrite(buffer,sizeof(char),1024,fp); remain_data -= 1024; bzero(buffer,1024); } fclose(fp); } |
Bu örnek kodlar sayesinde, server ve client arasında dosya transferi yapabilirsiniz. Ayrıca, bu örneklerin üzerine ekleyerek daha kompleks uygulamalar da geliştirebilirsiniz.