Python İle Socket Kütüphanesi Kullanarak Basit Bir Sohbet Uygulaması Nasıl Yapılır?

Python İle Socket Kütüphanesi Kullanarak Basit Bir Sohbet Uygulaması Nasıl Yapılır?
Python İle Socket Kütüphanesi Kullanarak Basit Bir Sohbet Uygulaması Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu projeyi gerçekleştirmek için bilgisayarınızda Python 3.10 veya daha güncel bir sürümün yüklü olması yeterlidir. Socket kütüphanesi, Python'un standart kütüphanesinin bir parçasıdır; bu nedenle ekstra bir paket yüklemenize gerek yoktur.

  • İşletim Sistemi: Windows, Linux veya macOS.
  • Python Sürümü: 3.10 ve üzeri.
  • Düzenleyici: VS Code, PyCharm veya herhangi bir metin editörü.
  • Terminal: Uygulamayı test etmek için iki ayrı terminal penceresi açmanız gerekecektir.

Başlamadan önce terminalinizi açıp python --version komutunu yazarak yüklü sürümünüzü doğrulayabilirsiniz. Eğer ortamınız hazırsa, ağ programlamanın temellerine giriş yapabiliriz.

Socket Programlamanın Temelleri

Socket, ağ üzerindeki uç noktayı temsil eder. Bir sunucu, belirli bir IP adresi ve port numarası üzerinden gelen bağlantıları dinler. İstemci ise bu adrese bağlanarak iletişim başlatır. İletişim, veri paketlerinin (byte dizileri) gönderilmesi ve alınması esasına dayanır.

Aşağıdaki tabloda, socket programlamada kullanılan temel yöntemlerin kısa bir özetini bulabilirsiniz:

Yöntem Açıklama Kullanım Amacı
socket() Yeni bir socket oluşturur. Bağlantı başlangıcı.
bind() Socket'i IP ve porta bağlar. Sunucu tarafında zorunlu.
listen() Bağlantı isteklerini bekler. Sunucu tarafında zorunlu.
accept() Gelen bağlantıyı kabul eder. Yeni bir istemci bağlantısı.
send() / recv() Veri gönderir veya alır. Mesajlaşma süreci.

Adım Adım Sunucu (Server) Tarafını Oluşturma

Sunucu, istemcilerden gelecek mesajları bekleyen ve bunları karşılayan taraftır. İlk olarak, sunucumuzun dinleyeceği bir port belirlemeli ve bağlantıları kabul etmeliyiz. Aşağıdaki kod, basit bir sunucu yapısını kurmanızı sağlar.

import socket

def sunucu_baslat():
    host = '127.0.0.1'  # Yerel makine
    port = 65432        # Standart port numarası

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind((host, port))
    server_socket.listen(1)

    print(f"Sunucu {host}:{port} adresinde dinliyor...")
    conn, addr = server_socket.accept()
    print(f"Bağlantı kuruldu: {addr}")

    while True:
        data = conn.recv(1024)
        if not data:
            break
        print(f"İstemciden gelen: {data.decode('utf-8')}")
        conn.sendall(b"Mesajiniz alindi.")

    conn.close()

if __name__ == "__main__":
    sunucu_baslat()

Bu kodda AF_INET IPv4 protokolünü, SOCK_STREAM ise TCP bağlantısını temsil eder. recv(1024) ifadesi, bir seferde en fazla 1024 byte veri alınacağını belirtir.

Adım Adım İstemci (Client) Tarafını Oluşturma

İstemci, sunucuya bağlanan ve mesaj gönderen taraftır. Sunucunun çalıştığı IP ve port bilgilerini kullanarak bir bağlantı talebi oluştururuz. İstemci kodu, sunucuya mesaj gönderip yanıt alacak şekilde tasarlanmıştır.

import socket

def istemci_baslat():
    host = '127.0.0.1'
    port = 65432

    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((host, port))

    mesaj = input("Sunucuya gönderilecek mesaj: ")
    client_socket.sendall(mesaj.encode('utf-8'))

    data = client_socket.recv(1024)
    print(f"Sunucudan gelen yanıt: {data.decode('utf-8')}")

    client_socket.close()

if __name__ == "__main__":
    istemci_baslat()

Burada encode('utf-8') kullanarak metin verisini byte dizisine çeviriyoruz; çünkü socket üzerinden sadece byte verisi gönderilebilir. Aynı şekilde, gelen byte verisini de decode('utf-8') ile metne dönüştürüyoruz.

Uygulamayı Test Etme ve Çalıştırma

Uygulamayı test etmek için iki ayrı terminal penceresi kullanmalısınız. İlk terminalde sunucuyu başlatın:

python server.py

İkinci terminalde istemciyi çalıştırın:

python client.py

İstemci terminaline bir mesaj yazdığınızda, sunucu terminalinde bu mesajın görüntülendiğini ve sunucunun "Mesajiniz alindi" yanıtını döndürdüğünü göreceksiniz. Bu basit döngü, ağ üzerinden veri iletiminin temelini oluşturur.

Sohbet Uygulamasını Geliştirme: Çoklu İletişim

Yukarıdaki örnek tek seferlik bir mesajlaşma sağlar. Gerçek bir sohbet uygulaması için while döngülerini daha verimli kullanmalı ve hata yönetimi eklemeliyiz. Aşağıdaki örnek, sürekli mesajlaşmaya izin veren bir yapı sunar.

# İstemci tarafı için sürekli döngü örneği
while True:
    mesaj = input("Siz: ")
    if mesaj.lower() == 'cikis':
        break
    client_socket.sendall(mesaj.encode('utf-8'))
    yanit = client_socket.recv(1024)
    print(f"Sunucu: {yanit.decode('utf-8')}")

Bu yapıyı sunucu tarafında da benzer bir döngü ile destekleyerek, tarafların birbirine sürekli mesaj göndermesini sağlayabilirsiniz.

Kritik Güvenlik Uyarısı: Bu uygulama sadece eğitim amaçlıdır. Üretim ortamında socket haberleşmesi yaparken verilerin şifrelenmesi (SSL/TLS) zorunludur. Ayrıca, gelen verileri asla doğrudan çalıştırmayın veya veritabanı sorgularına doğrudan eklemeyin; bu durum SQL Injection veya Komut Enjeksiyonu gibi ciddi güvenlik açıklarına yol açabilir.

Sıkça Sorulan Sorular

Socket ile sohbet uygulaması yaparken neden TCP kullanmalıyız?

TCP, verilerin kaybolmadan ve gönderildiği sırayla ulaşmasını garanti eder. UDP gibi protokoller ise daha hızlıdır ancak veri kaybına toleranslıdır; bu nedenle sohbet uygulamalarında TCP tercih edilir.

1024 byte sınırı neden var?

Bu bir tampon (buffer) boyutudur. Çok büyük veriler gönderirken bu değeri artırabilirsiniz, ancak ağ paketlerinin parçalanmasını yönetmek için genellikle 4096 veya 8192 gibi değerler tercih edilir.

Farklı bilgisayarlar arasında nasıl bağlantı kurarım?

127.0.0.1 (localhost) yerine sunucunun yerel ağdaki IP adresini (örneğin 192.168.1.5) kullanmalı ve güvenlik duvarı ayarlarından ilgili portu dış bağlantılara açmalısınız.

Bağlantı koptuğunda ne yapmalıyım?

try-except blokları kullanarak ConnectionResetError veya BrokenPipeError hatalarını yakalamalı ve socket'i düzgün bir şekilde kapatıp yeniden bağlanma mantığı kurmalısınız.

Bu uygulama ile aynı anda birden fazla kişi sohbet edebilir mi?

Hayır, bu temel örnek sadece tek bir istemciyi destekler. Çoklu kullanıcı için threading (iş parçacığı) kütüphanesini kullanarak her bağlantıyı ayrı bir süreçte yönetmeniz gerekir.

Uygulamayı Gerçek Dünya Senaryolarına Hazırlama: Hata Ayıklama ve Dayanıklılık

Geliştirdiğiniz basit sohbet uygulaması, yerel ağda (localhost) kusursuz çalışsa da, gerçek dünya senaryolarında ağ kesintileri, geçersiz veri paketleri ve beklenmedik bağlantı sonlanmaları ile karşılaşmanız kaçınılmazdır. Uygulamanızın "çökmemesi" için hata yönetimi (exception handling) mekanizmalarını güçlendirmeniz gerekir.

Özellikle socket.error ve ConnectionResetError gibi hataları yakalamak, uygulamanızın kararlılığını doğrudan etkiler. Aşağıdaki kod bloğu, istemci tarafında bağlantı kopmalarını nasıl daha güvenli yönetebileceğinizi gösterir:

import socket

def client_program():
    host = '127.0.0.1'
    port = 5000
    client_socket = socket.socket()

    try:
        client_socket.connect((host, port))
        print("Sunucuya bağlandı.")
        
        while True:
            message = input("Mesajınız: ")
            if message.lower() == 'çıkış':
                break
            
            try:
                client_socket.send(message.encode())
                data = client_socket.recv(1024).decode()
                print(f"Sunucudan gelen: {data}")
            except ConnectionResetError:
                print("Sunucu bağlantıyı kopardı.")
                break
                
    except ConnectionRefusedError:
        print("Sunucuya ulaşılamıyor. Lütfen sunucunun çalıştığından emin olun.")
    finally:
        client_socket.close()
        print("Bağlantı kapatıldı.")

if __name__ == '__main__':
    client_program()

Performans ve Ölçeklenebilirlik İçin İleri İpuçları

Uygulamanızın performansını artırmak ve daha büyük ölçekli projelere hazırlık yapmak için aşağıdaki stratejileri göz önünde bulundurmalısınız:

  • Non-blocking Sockets: Varsayılan olarak socket işlemleri "blocking" (engelleyici) moddadır. Yani recv() çağrısı veri gelene kadar programı durdurur. socket.setblocking(False) kullanarak uygulamanızın veri bekleme süresinde diğer işlemleri yapmasını sağlayabilirsiniz.
  • Buffer Yönetimi: 1024 byte sınırı küçük mesajlar için yeterlidir ancak dosya transferi gibi işlemler yapacaksanız, veriyi parçalar halinde okuyan bir döngü kurmanız gerekir.
  • JSON Kullanımı: Ham metin göndermek yerine, verilerinizi json kütüphanesi ile paketleyerek gönderin. Bu, mesajlarınıza kullanıcı adı, zaman damgası veya mesaj tipi gibi meta veriler eklemenizi kolaylaştırır.

Örneğin, veriyi JSON formatında göndermek için şu yapıyı kullanabilirsiniz:

import json

# Mesajı göndermeden önce
payload = {
    "user": "Kullanici1",
    "message": "Merhaba dünya!",
    "timestamp": "2023-10-27 10:00:00"
}
client_socket.send(json.dumps(payload).encode())

# Mesajı aldıktan sonra
data = client_socket.recv(1024).decode()
message_dict = json.loads(data)
print(f"{message_dict['user']}: {message_dict['message']}")

Bu yaklaşım, uygulamanızın sadece bir sohbet aracı değil, aynı zamanda farklı veri tiplerini taşıyabilen bir ağ protokolü haline gelmesini sağlar. Projenizi bir adım öteye taşımak için select veya selectors modüllerini inceleyerek I/O multiplexing yöntemlerini öğrenebilir, böylece tek bir thread ile onlarca bağlantıyı yönetebilirsiniz.

Sonuç

Python ile socket kütüphanesini kullanarak basit bir sohbet uygulaması geliştirmek, ağ programlamanın mantığını anlamak için harika bir başlangıçtır. Bu rehberde, sunucu ve istemci arasındaki temel veri alışverişini, byte dönüşümlerini ve bağlantı yönetimini öğrendiniz. Bir sonraki adım olarak, threading kütüphanesini araştırarak aynı anda birden fazla istemciyi destekleyen bir sohbet odası yapmayı deneyebilirsiniz. Yazılım geliştirme sürecinde, güvenliğe her zaman öncelik vermeyi ve kodunuzu modüler tutmayı unutmayın.

Bu yazıya tepkinizi paylaşın:
Selin Yılmaz

Sürdürülebilir yaşam ve pratik ev yönetimi üzerine içerik stratejileri geliştiriyorum. Yalın anlatımı ve uygulanabilirliği ön planda tutan bir yazı dilim var.

Yorumlar (0)

Yorum Yaz