Bu yazıda Python ile TCP ve UDP protokollerini kullanarak socket nesnesi aracılığıyla server-client arasında network üzerinden iletişim kurmayı göreceğiz.

Python içerisinde network’e bağlı server ve client’lar oluşturmak için çeşitli third-party araçlar programcılar tarafından kullanılmaktadır. Fakat bütün bu araçların çekirdek modülü socket adı verilen modüldür. Bu modül hızlı bir biçimde TCP ve UDP client ve serverları yazmak, ham soketleri kullanmak için gerekli bütün parçaları barındırır.  Böylece çabucak, basit client ve serverlar oluşturmak mümkün hale gelir.

Soket nedir ?

Soketler bir network bağlantısının soyutlanmasına yarayan programlama nesneleridir. Çift yönlü olarak iletişim kurmamıza olanak sağlarlar. Bir kere bağlantı sağlandığında, veri iletmeye hazır olduklarında, veri iletmek veya almak için kullanılabilirler. Soket TCP ve UDP protokollerini implemente ederek kolaylıkla yönetebileceğimiz bir arayüzdür.

Notlar :

  • Örneklerde kullandığımız 127.0.0.1 IP adresi bilgisayarın kendini işaret etmektedir. (localhost)
  • Kodların Python3 versiyonlarını aşağıda bulabilirsiniz:

Şimdi basit bir TCP istemcisi yazarak başlayalım.

TCP İstemcisi (TCP Client)

Bir sistem içerisinde hemen bir TCP client’i oluşturmak bazı durumlarda ihtiyaç duyulabilecek gayet kullanışlı bir şeydir. Aşağıda basit bir TCP client’i görülmektedir :

Socket objesini AF_INET ve SOCK_STREAM  parametreleri ile oluşturuyoruz. ➊

  • AF_INET parametresi standart IPv4 adresi ya da hostname kullanacağımızı söylüyor.
  • SOCK_STREAM bunun bir TCP client’i olacağını belirtiyor.

Server’a bağlanıyoruz.➋

Örnek bir data gönderiyoruz.➌

Son adımda ise gelen cevabı (response) ekrana yazdırıyoruz.➍

Bu, bir TCP client’inin en basit biçimidir. Unutmamak gerekir ki yukarıdaki kod parçasında, socket’ler hakkında kesinlikle farkında olmak istediğiniz bazı ciddi varsayımlar yapıyoruz.

İlk varsayım, bağlantımızın her zaman başarılı olacağı varsayımıdır.

İkincisi ise sunucunun her zaman önce veri göndermemizi bekleyeceği varsayımıdır. (Aksine serverlar size önce veri yollayıp cevabınızı bekleyebilir.)

Üçüncü varsayımımız sunucunun her zaman bize zamanında veri göndereceğidir. Bu varsayımları büyük ölçüde basitlik adına yapıyoruz.

UDP İstemcisi (UDP Client)

Python UDP Client’da  TCP Client’a benzerdir. Birkaç değişiklik yaparak paketleri UDP formunda yollayacağız.

Görebileceğiniz üzere soket türünü SOCK_DGRAM olarak değiştiriyoruz. ➊

sendto() ile veriyi göndermek sunucuya veriyi yolluyoruz. ➋

UDP bağlantısız protokol (connectionless) olduğundan, önceden connect () çağrısı yoktur. UDP karşıda bir cihaz olup olmaması ile ilgilenmez. Verinin cihaz tarafından alınacağı garanti değildir.

Son adım, recvfrom () fonksiyonu ile UDP datasını çağırmak. ➌

Dikkat edersek bu sefer hem datayı, hem de uzaktaki host ve portun bilgilerini döndürüyor.

Burada amacımız detaylı bir client tasarlamaktan ziyade günlük alıştırmaları yürütebilecek kadar hızlı, kolay ve güvenilir bir client’lar elde etmek. Şimdi server’lar ile devam edelim.

TCP Server

Python ile TCP Server oluşturmak da Client oluşturmak kadar kolaydır. Command shell yazarken veya proxy oluştururken kendi TCP serverımızı kullanmak isteyebiliriz. Standart multi-threaded bir TCP server ile başlayalım.

Başlamak için önce sunucunun IP adresini ve dinlemek istediğimiz portunu belirtiyoruz. ➊

Daha sonra sunucuya dinlemeyi başlatmasını söylüyoruz. Parametresi (backlog – sıradaki maximum bağlantı sayısı) olarak 5 veriyoruz. ➋

Ardından alt kısma gelecek olursak (while True:) sunucuyu main döngüsü içerisine koyuyoruz. Bu döngü içerisinde gelecek bağlantıyı bekleyecek.

Bir istemci bağlantıyı gerçekleştirdiğinde, client soketini alıp client değişkenine aktarıyor ve yine uzak bağlantı detaylarını da addr değişkenine aktarıyoruz. ➍

Ardından handle_client fonksiyonumuzu işaret eden yeni bir thread nesnesi oluşturuyoruz ve client soket nesnesi’ni argüman olarak gönderiyoruz.

Sunucuya gelen Client bağlantısını işlemek için thread’i başlatıyoruz. ➎ Artık main server döngüsü gelecek olan başka bir bağlantıyla başa çıkmaya hazır.

handle_client fonksiyonu recv()‘i çağırarak istemcinin gönderdiği mesajı alıp. Ardından client’a basit bir mesaj gönderiliyor.

Daha önce yapmış olduğumuz TCP istemcisini kullanırsanız, sunucuya bazı test paketleri gönderebilirsiniz.

Aşağıdakine benzer bir çıktı görmelisiniz:

Bu kadar! Bu oldukça basit, kullanışlı bir kod parçaları ile TCP ve UDP ile haberleşmeyi gördük. Bir sonraki bölümde netcat yedeği ve bir TCP proxy’si oluşturarak genişleteceğiz.