Ağ Programlama (Networking) Temelleri
Bugün yazdığımız uygulamaların neredeyse hiçbiri yalnız çalışmaz: bir mobil uygulama sunucuya istek atar, bir web sitesi veritabanına bağlanır, mikroservisler birbirleriyle konuşur. Bütün bunların altında ağ programla…
Ağ Programlama (Networking) Temelleri
Bugün yazdığımız uygulamaların neredeyse hiçbiri yalnız çalışmaz: bir mobil uygulama sunucuya
istek atar, bir web sitesi veritabanına bağlanır, mikroservisler birbirleriyle konuşur. Bütün
bunların altında ağ programlama vardır. İyi haber şu ki Java, ağ iletişimini standart
kütüphanesi (java.net) ile baştan destekler; üstelik bunu dosya okur gibi, akışlarla (stream)
yapmana izin verir. Bu bölümde ağın temel kavramlarını ve Java'nın bunları nasıl modellediğini,
internet gerektirmeden, kendi makinende çalışan örneklerle öğreneceğiz.
Ağın temel kavramları
Bir ağ iletişimini anlamak için birkaç kavramı netleştirelim:
- IP adresi: Ağdaki her makinenin kimliği. IPv4 (
192.168.1.5) veya IPv6 (2001:db8::1). - Port: Bir makinedeki belirli bir servisin "kapı numarası" (0–65535). Web sunucusu 80/443, veritabanı 5432/3306 gibi. Bir IP + port = bir uç nokta (endpoint).
- localhost / loopback (
127.0.0.1,::1): "Bu makinenin kendisi". Ağ kartına bile gitmeden, makinenin kendi içinde iletişim. Test için idealdir (ve internet gerektirmez). - DNS: İnsan-okunur adları (
example.com) IP adreslerine çeviren "telefon rehberi". - İstemci / Sunucu (client/server): Sunucu bir portu dinler ve bağlantı bekler; istemci o porta bağlanır. İstek-cevap bu kanal üzerinden akar.
Adresleri tanımak: InetAddress
Java'da bir makineyi/IP'yi InetAddress temsil eder. Ad↔IP çözümleme, loopback erişimi ve
ulaşılabilirlik testi sağlar:
InetAddress loopback = InetAddress.getLoopbackAddress(); // 127.0.0.1 InetAddress localhost = InetAddress.getByName("localhost"); InetAddress benim = InetAddress.getLocalHost(); // bu makine loopback.isReachable(1000); // ulaşılabilir mi?
Örnek 1 (./Ornek1.java) bunları çalıştırır (loopback ve yerel makineyle; internet gerekmez) ve
IPv4/IPv6 ayrımını gösterir.
İki taşıma protokolü: TCP ve UDP
Veriyi ağ üzerinden taşımanın iki temel yolu vardır ve seçim işin doğasına bağlıdır:
TCP (Transmission Control Protocol)
Bağlantı tabanlı ve güvenilir: önce bir bağlantı kurulur (handshake), sonra veri sırayla, kayıpsız ve doğrulanarak akar. Java'da:
- Sunucu:
ServerSocketbir portu dinler,accept()ile bağlantı bekler (bloklar). - İstemci:
Socketile sunucuya bağlanır. - İki taraf da giriş/çıkış akışlarıyla (
getInputStream/getOutputStream) konuşur — tıpkı dosya okur/yazar gibi.
ServerSocket sunucu = new ServerSocket(port); Socket istemci = sunucu.accept(); // bağlantı bekle // ... in/out akışlarıyla konuş ... Socket soket = new Socket("localhost", port); // istemci bağlanır
Örnek 2 (./Ornek2.java) tek bir JVM'de bir TCP echo sunucusu (gelen satırı geri yansıtan)
ve ona bağlanan bir istemci kurar. HTTP, FTP, veritabanı bağlantıları... hepsi TCP üzerindedir.
UDP (User Datagram Protocol)
Bağlantısız ve hızlı ama güvencesiz: handshake yoktur, her paket (datagram) bağımsız
gönderilir; sıra ve teslim garanti edilmez. Java'da DatagramSocket ve DatagramPacket kullanılır.
DatagramSocket soket = new DatagramSocket(); soket.send(new DatagramPacket(veri, veri.length, adres, port)); soket.receive(paket);
Örnek 3 (./Ornek3.java) loopback üzerinde bir UDP gönder/al döngüsü gösterir. UDP; canlı
video/ses, çevrim içi oyunlar ve DNS gibi hızın az kayıptan önemli olduğu yerlerde kullanılır.
| TCP | UDP | |
|---|---|---|
| Bağlantı | Var (handshake) | Yok |
| Güvenilirlik | Yüksek (sıralı, kayıpsız) | Düşük (kayıp olabilir) |
| Hız | Görece yavaş | Hızlı |
| Kullanım | Web, dosya, DB | Video/ses, oyun, DNS |
Bloklama (blocking) ve thread'ler
Klasik soket API'si bloklayıcıdır: accept() bağlantı gelene, read() veri gelene kadar
bekler. Bu yüzden gerçek sunucular her istemciyi ayrı bir thread'de (veya bir thread havuzunda)
karşılar — böylece bir istemci diğerlerini bekletmez. Bunu bir sonraki konuda (Socket Programlama)
çok istemcili bir sunucuyla göreceğiz. (Çok sayıda eşzamanlı bağlantı için Java 21'in sanal
thread'leri burada büyük avantaj sağlar.)
Özet
Ağ programlamanın temel kavramlarını (IP, port, localhost/loopback, DNS, istemci/sunucu),
adresleri tanımak için InetAddress'i ve iki taşıma protokolünü — güvenilir TCP ile hızlı
UDP — kendi makinende çalışan örneklerle öğrendik. Sırada, TCP soketleriyle gerçek istemci-
sunucu uygulamaları yazmayı derinleştiriyoruz: Socket Programlama.
▶ Kod Örnekleri(3)
Ornek1
çalıştırılabilir1// Ornek1: InetAddress — makineleri ve IP adreslerini tanımak.
2// Ağ programlamanın ilk adımı: "kiminle konuşacağım?" — adres çözümleme.
3// Çalıştırma: java Ornek1.java
4import java.net.InetAddress;
5
6public class Ornek1 {
7
8 public static void main(String[] args) {
9 // Loopback (127.0.0.1 / ::1): her zaman "bu makinenin kendisi". İnternet gerektirmez.
10 InetAddress loopback = InetAddress.getLoopbackAddress();
11 System.out.println("Loopback adresi : " + loopback.getHostAddress());
12
13 try {
14 // localhost adını çöz (loopback'e karşılık gelir).
15 InetAddress localhost = InetAddress.getByName("localhost");
16 System.out.println("localhost -> IP : " + localhost.getHostAddress());
17
18 // Bu makinenin ağ adı ve IP'si.
19 InetAddress benim = InetAddress.getLocalHost();
20 System.out.println("Bu makine (ad) : " + benim.getHostName());
21 System.out.println("Bu makine (IP) : " + benim.getHostAddress());
22
23 // isReachable: hedefe ulaşılabilir mi? (loopback her zaman ulaşılabilir.)
24 System.out.println("Loopback erişilebilir mi? " + loopback.isReachable(1000));
25
26 // IPv4/IPv6 ayrımı:
27 System.out.println("\nLoopback IPv4 mü? " + (loopback instanceof java.net.Inet4Address));
28 } catch (Exception e) {
29 System.out.println("Adres çözümleme uyarısı: " + e.getMessage());
30 }
31
32 System.out.println("""
33
34 --- InetAddress ne işe yarar? ---
35 Ağda her makine bir IP adresiyle (IPv4: 192.168.1.5, IPv6: 2001:db8::1) tanınır.
36 İnsanlar adları (örn. example.com) kullanır; DNS bunları IP'ye çevirir.
37 InetAddress: ad<->IP çözümleme, loopback/localhost, ulaşılabilirlik testi sağlar.
38 (Bu örnek internet GEREKTİRMEZ; loopback ve yerel makineyle çalışır.)""");
39 }
40}Ornek2
çalıştırılabilir1// Ornek2: TCP — güvenilir, bağlantı tabanlı iletişim (tek JVM'de echo sunucu + istemci).
2// Çalıştırma: java Ornek2.java
3import java.io.BufferedReader;
4import java.io.IOException;
5import java.io.InputStreamReader;
6import java.io.PrintWriter;
7import java.net.ServerSocket;
8import java.net.Socket;
9
10public class Ornek2 {
11
12 public static void main(String[] args) throws Exception {
13 // ServerSocket'i 0 (ephemeral) port ile açarız: işletim sistemi boş bir port atar.
14 ServerSocket sunucu = new ServerSocket(0);
15 int port = sunucu.getLocalPort();
16 System.out.println("TCP echo sunucusu başladı, port: " + port);
17
18 // Sunucu ayrı bir thread'de tek bir istemciyi karşılar (gelen satırı geri yansıtır).
19 Thread sunucuThread = new Thread(() -> {
20 try (Socket istemci = sunucu.accept(); // bağlantı bekle (bloklar)
21 BufferedReader in = new BufferedReader(new InputStreamReader(istemci.getInputStream()));
22 PrintWriter out = new PrintWriter(istemci.getOutputStream(), true)) {
23 String satir;
24 while ((satir = in.readLine()) != null) {
25 System.out.println(" [sunucu] alındı: " + satir);
26 out.println("ECHO: " + satir); // geri gönder
27 if (satir.equals("bitir")) break;
28 }
29 } catch (IOException e) {
30 System.out.println("sunucu hatası: " + e.getMessage());
31 }
32 });
33 sunucuThread.start();
34
35 // İstemci: localhost:port'a bağlanır, mesaj gönderir, cevabı okur.
36 try (Socket soket = new Socket("localhost", port);
37 PrintWriter out = new PrintWriter(soket.getOutputStream(), true);
38 BufferedReader in = new BufferedReader(new InputStreamReader(soket.getInputStream()))) {
39 for (String mesaj : new String[]{"merhaba", "nasılsın", "bitir"}) {
40 out.println(mesaj);
41 System.out.println("[istemci] gönderdi: " + mesaj + " | cevap: " + in.readLine());
42 }
43 }
44
45 sunucuThread.join();
46 sunucu.close();
47 System.out.println("""
48
49 --- TCP (Transmission Control Protocol) ---
50 Bağlantı tabanlı, GÜVENİLİR: veri sırayla, kayıpsız ve doğrulanarak ulaşır.
51 Akış: ServerSocket.accept() bağlantı bekler; istemci Socket ile bağlanır.
52 Her iki taraf giriş/çıkış akışlarıyla (stream) konuşur — tıpkı dosya gibi.
53 HTTP, FTP, veritabanı bağlantıları... hepsi TCP üzerinde çalışır.""");
54 }
55}Ornek3
çalıştırılabilir1// Ornek3: UDP — hızlı, bağlantısız iletişim (tek JVM'de datagram gönder/al).
2// Çalıştırma: java Ornek3.java
3import java.net.DatagramPacket;
4import java.net.DatagramSocket;
5import java.net.InetAddress;
6
7public class Ornek3 {
8
9 public static void main(String[] args) throws Exception {
10 InetAddress loopback = InetAddress.getLoopbackAddress();
11
12 // Sunucu tarafı: bir UDP soketi aç, bir paket bekle, cevap gönder.
13 DatagramSocket sunucu = new DatagramSocket(0); // ephemeral port
14 int port = sunucu.getLocalPort();
15 System.out.println("UDP sunucusu, port: " + port);
16
17 Thread sunucuThread = new Thread(() -> {
18 try {
19 byte[] tampon = new byte[1024];
20 DatagramPacket gelen = new DatagramPacket(tampon, tampon.length);
21 sunucu.receive(gelen); // paket bekle (bloklar)
22 String mesaj = new String(gelen.getData(), 0, gelen.getLength());
23 System.out.println(" [sunucu] alındı: " + mesaj);
24
25 // Cevabı, paketin geldiği adrese/porta geri gönder.
26 byte[] cevap = ("ECHO: " + mesaj).getBytes();
27 sunucu.send(new DatagramPacket(cevap, cevap.length, gelen.getAddress(), gelen.getPort()));
28 } catch (Exception e) {
29 System.out.println("sunucu hatası: " + e.getMessage());
30 }
31 });
32 sunucuThread.start();
33
34 // İstemci tarafı: bir paket gönder, cevabı al.
35 try (DatagramSocket istemci = new DatagramSocket()) {
36 byte[] veri = "merhaba UDP".getBytes();
37 istemci.send(new DatagramPacket(veri, veri.length, loopback, port));
38
39 byte[] tampon = new byte[1024];
40 DatagramPacket cevap = new DatagramPacket(tampon, tampon.length);
41 istemci.receive(cevap);
42 System.out.println("[istemci] cevap: " + new String(cevap.getData(), 0, cevap.getLength()));
43 }
44
45 sunucuThread.join();
46 sunucu.close();
47 System.out.println("""
48
49 --- UDP (User Datagram Protocol) ---
50 Bağlantısız, HIZLI ama GÜVENCESİZ: paket sırası/teslimi garanti edilmez.
51 Bağlantı kurma (handshake) yok; her paket (datagram) bağımsız gönderilir.
52 Kullanım: canlı video/ses, oyunlar, DNS — hızın, az kaybın önemli olmadığı yerler.
53 TCP vs UDP: TCP güvenilir+sıralı (web/dosya); UDP hızlı+kayıplı (gerçek zamanlı).""");
54 }
55}