Python ve Temel Ağ İşlemleri

Python ile Klavye Olaylarını Okuma

Her programcı “Bunu (ağ işlemini) programlı olarak nasıl yaparım?” sorusunu sormuştur. bir noktada. İnsana yönelik yazılım istemcilerinin kolaylaştırdığı web sitesinde gezinme, dosya aktarımları ve e-posta gönderme veya alma gibi rutin görevler, bir yazılım çözümüne entegre edilmeleri gerektiğinde esrarengiz ve karmaşık görevler gibi görünmektedir. Bu Python programlama öğreticisinin amacı, bir geliştiricinin Python programlama dilini kullanarak üstlenmesi gerekebilecek daha rutin ağ oluşturma görevlerinden bazılarını yıkmaktır.

Bu makale, MacOS ve Python’a yapılan herhangi bir referansı bariz bir şekilde atlamaktadır. Bunun nedeni, Apple’ın Python’u MacOS’tan kaldırmaya karar vermesidir.

Python’u çevrimiçi bir sınıf aracılığıyla öğrenmekle ilgileniyor musunuz? Listelenen harika bir makalemiz var. Python Öğrenmek için En İyi Çevrimiçi Kurslar.

Python’da Soketler

Hem IBM, Oracle hem de Linux Manual Pages tarafından belirtildiği gibi bir soketin ortak tanımı, “iki yönlü bir iletişim kanalının uç noktası”dır. Soketler, nasıl geliştirildiğine veya hangi dilde oluşturulduklarına bakılmaksızın, ağ özellikli herhangi bir uygulamanın temelidir.

Soket bağlantısı olmadan hiçbir gelişmiş ağ işlemi gerçekleştirilemez. Bu nedenle, soket bağlantıları çok “düşük seviye” olarak kabul edilir. Ancak uzmanlık olmadan bile, soket bağlantıları teşhis açısından kendi başlarına çok faydalı olabilir. Ek olarak, özel veya standart olmayan bir iletişim protokolü uygulanıyorsa, bu bağlantıyı uygulamak için bir soket bağlantısı kullanılabilir.

Python’daki soketler bir Adres Ailesi ve bir Tip. Adres Ailesine bağlı olarak, isteğe bağlı bir protokol numarası belirlenebilir. Bir soket oluşturmak için açık bir dosya akışı da kullanılabilir. Python’daki soketler, Linux’ta yerleşik olan C/C++ kitaplık işlevlerinin üzerine inşa edildiğinden, Python’da soketlerin nasıl uygulanacağı hakkında bilgi almak için bu kitaplıkların aynı kılavuz sayfaları kullanılabilir. Aşağıdaki bilgiler doğrudan şu komutla erişilebilen Linux Kılavuz Sayfasından gelir:

$ man 2 socket

Şekil 1 – Unix Sockets için ikinci kılavuz sayfası bölümünün seçilen çıktısı

Bu komut, “soket” konusu için kılavuz sayfasının “Bölüm 2″sine erişir. Belirli bir konu için manuel girişin 2. Bölümü genellikle aşağıdakiler hakkında bilgi sağlar: Linux Sistem Çağrıları. Bir giriş eğitimi amacıyla, odak noktası en yaygın Adres Ailelerinden biri olacaktır. AF_INET IPv4 tabanlı ağ iletişimi ve SOCK_STREAM güvenilir iki yönlü iletişim sağlayan soket tipi. Ve birçok farklı Adres Ailesi ve Türü listelenmiş olsa da tümü Linux veya Windows’ta desteklenmez. Bunun da ötesinde, bir programcı Python içinde desteklenen Adres Aileleri ve Türleri ile daha da sınırlandırılır. Windows Python yorumlayıcısı bu sabitlerin bir alt kümesini desteklerken, Linux kılavuz sayfalarında yer alan bilgiler Windows’ta mevcut olmayacaktır.

Bu bilgiyi almanın alternatif bir yolu, bir arama motoruna basitçe “man 2 socket” yazmaktır. Linux kılavuz sayfalarının tümü çevrimiçi olarak mevcuttur.

Bir soket başlatıldığında, bir veya daha fazla sokete bağlanmalıdır. arayüzler ve tek Liman. Arayüz, cihazdaki mevcut herhangi bir ağ arayüzünü ifade eder. Bu makaledeki örnekler tüm arabirimlere bağlanacaktır, ancak tek bir arabirime bağlanmanın istenebileceği durumlar olabilir. Linux’taki arayüzleri listelemek için şu komutu kullanın:

$ ip a

Aşağıda bu komutun örnek bir çıktısı verilmiştir:

Python Soket örneği

Şekil 2 – Bir cihazdaki arayüzlerin örnek listesi

127.0.0.1 bu geri döngü arayüzü. Bu arabirim kullanılırsa, bir sunucuya yapılabilecek bağlantılar yalnızca o sunucudan gelen bağlantılar olacaktır. Bu bağlantılar, cihaz bir ağa bağlı olsa bile herhangi bir ağ üzerinde herhangi bir yere yönlendirilmez. Burada gösterilen diğer arayüz, 10.0.2.15, yerel ağdan bağlantılara izin verir, ancak bu yönlendirilemez bir IP adresidir. Ağda kullanılan yönlendirici bağlantı noktası yönlendirme için yapılandırılmışsa, daha geniş İnternet bağlantılarına izin verilebilir.

Windows’ta arayüzler şu komut kullanılarak listelenebilir:

C…> ipconfig

Bu komut, aşağıda gösterilene benzer bir çıktı verir:

IPConfig Komutu

Şekil 3 – Windows’ta ipconfig komutunun örnek çıktısı

127.0.0.1’in geri döngü arabiriminin Windows’ta listelenmeyebileceğini, ancak yine de mevcut olduğunu unutmayın.

Limanla ilgili olarak, 60000 diğer uygulamaların muhtemelen kullanmadığı yüksek numaralı bir bağlantı noktası olduğu için seçilmiştir. Belirli bir bağlantı noktasına yalnızca bir soket bağlanabilir ve başka bir soket zaten bağlı olan bir bağlantı noktasına bağlanmaya çalışırsa, bir istisna ortaya çıkar. Ayrıca, bir soketin hangi bağlantı noktasına bağlanabileceği konusunda bir kısıtlama olmasa da, belirli bağlantı noktaları söz konusu olduğunda belirli beklentiler vardır. Örneğin, liman 25 bir SMTP bağlantı noktası olması “beklenir”; limanlar 80 ve 443 sırasıyla HTTP ve HTTPS bağlantı noktaları olması “beklenir”; Liman 22 bir SSH bağlantı noktası olması “beklenir”. Geliştiriciler, uygulamaları için seçilen bağlantı noktasının büyük bir uygulama tarafından kullanılan popüler bir bağlantı noktası olmadığını her zaman kontrol etmeli ve doğrulamalıdır.

Okumak: Python’da Metin Kazıma

Python Kullanarak Temel Bir Sunucu Nasıl Oluşturulur

Aşağıdaki kod, Python’da, bir kullanıcının bağlanırken yazdıklarını tekrarlayan ve ardından o kullanıcının bağlantısını kesen ilkel bir sunucu oluşturur. Ayrıca uzak kullanıcının sunucuyu kapatması için bir yol sağlar. Geçersiz bir Aile Adresi veya Türü kullanarak herhangi bir soket oluşturma girişiminin, bir İşlem desteklenmiyor hata.

# demo-basic-server.py

import datetime
import socket
import sys

def main(argv):
 try:
  # Any use of an unsupported Address Family or Type will give an
  # "Operation not supported" error.
  # This method does not allow for reusing of previously closed 
  # sockets. This means that depending on which state the socket
  # was in when the socket was closed, this program may not be 
  # immediately restartable. This is resolved by setting reusability
  # in the socket options (see the next line)
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

  # This option enables a socket to be reused without having to wait
  # for a timeout to expire.
  s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

  # Network addresses in Python are represented as "(interface, port)"
  # including the parenthesis.

  # Bind to all interfaces on the device, on port 60000
  # Ports below 1024 must be bound as root. In this example, if it
  # necessary to bind to a specific interface for this device, then 
  # the '' below would be replaced with '127.0.0.1' or whatever other 
  # interface is configured.
  s.bind(('', 60000))

  # If the listen method does not immediately follow the bind method, 
  # then an "Invalid argument" error will occur. Mote that as Python 3.5
  # a parameter to this is optional.
  s.listen()

  # Since the accept method blocks, there is no way to trap a
  # Keyboard interrupt within the while loop.

  try:
   while True:
    # The accept method will block until a connection is made.
    conn, addr = s.accept()
    print ("Got a connection from [" + str(addr) + "] at [" + 
     str(datetime.datetime.now()) + "]")
    # This command presumes UTF-8 encoding for strings. If this is not
    # the default system encoding, then it must be changed or else the
    # command will raise an exception.
    conn.sendall(b"You connected at [" + bytes(str(datetime.datetime.now()), 'utf-8') 
     + b"]n")

    # Read any input from the connection, so it can be echoed back.
    # The 4096 value is recommended by the official Python documentation.
    # The command blocks until either the data count below is received 
    # or when a user enters a newline character.
    data = conn.recv(4096)

    conn.sendall (b"You sent: [" + data + b"]n")

    # Do some rudimentary processing. Note the binary data conversion.
    if b"shutdown" == data.strip().lower():
     conn.sendall(b"You told me to shut down!n")
     raise Exception ("Remote user initiated shutdown.")

    conn.close()
  except KeyboardInterrupt:
   print ("User pressed Ctrl-C, stopping.")
  except Exception as err:
   print ("Execution ended because of [" + str(err) + "]")
  # Closes the socket.
  s.close()
  s = None

 except Exception as err:
  print ("Socket listen failed due to error [" + str(err) + "]")


if __name__ == "__main__":
 main(sys.argv[1:])

Bu kodla aynı cihazda çalışan herhangi bir güvenlik duvarı veya virüsten koruma programı, Python yorumlayıcısının bağlantı noktalarına bağlanmasına ve ağ üzerinden iletişim kurmasına izin verecek şekilde yapılandırılmalıdır.

Yukarıdaki örnek, sunucuya bağlanmak için telnet istemcisini kullanır. Bu, son kullanıcının komutları etkileşimli olarak doğrudan sunucuya göndermesine olanak tanır. Ancak, programatik bir temel istemcinin gerekli olduğu zamanlar vardır.

Python’da Temel İstemci Nasıl Oluşturulur

Yazarken dikkat edilmesi gereken ilk şey hiç müşteri bir sunucu ile programlı olarak iletişim kuran, sunucunun davranış mükemmel bir şekilde eşleşir. Yukarıdaki temel sunucu durumunda, bağlantıda bir mesaj gönderilir, ardından bir giriş beklenir ve ardından başka bir mesaj gönderilir. Tüm bunlardan sonra, sunucu istemcinin bağlantısını keser.

Bu davranış tam olarak eşleşmezse, öngörülemeyen eylemler gerçekleşir. İletişim kurulan sunucuya bağlı olarak, bu büyük sorunlara neden olabilir.

Aşağıdaki Python kodu, yukarıdaki temel sunucu kodunu tamamlar:

# demo-basic-client.py

import socket
import sys

def ProcessConnection (inSocket, message):
 # Note how the client program has to match the functionality of the
 # server program.
 # Get any message first.
 inMsg = GetData (inSocket)
 print ("Got Message [" + inMsg + "]")
 # Some sample commands... 
 SendData (inSocket, message)
 inMsg = GetData (inSocket)
 print ("Got Second Message [" + inMsg + "]")

def GetData (inSocket):
 message = ""
 try:
  message = inSocket.recv(4096)
 except socket.error as err:
  print ("Couldn't receive message due to error [" + str(err) + "]")
 
 return message.decode()

def SendData (inSocket, message):
 try:
  inSocket.sendall(bytes(message, "utf-8"))
  print ("Successfully sent message [" + message + "]")
 except socket.error as err:
  print ("Couldn't send message due to error [" + str(err) + "]")

def main(argv):
 try:
  # As it was with the server, any use of an unsupported Address 
  # Family or Type will give an "Operation not supported" error.
  # This method likewise does not allow for reusing of previously 
  # closed sockets. This means that depending on which state the 
  # socket was in when the socket was closed, this program may not be 
  # immediately restartable. This is resolved by setting reusability
  # in the socket options (see the next line)
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

  # This option enables a socket to be reused without having to wait
  # for a timeout to expire.
  s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  
  # Connect to the server. Both the host and port must match the 
  # what the server is listening on. In this case we connect on the 
  # localhost interface.
  s.connect (("127.0.0.1", 60000))
 
  msgFromPrompt = "Hello!"
  try:
   msgFromPrompt = sys.argv[1]
  except Exception as err:
   print ("No message specified. Defaulting to "Hello!"")
   msgFromPrompt = "Hello!"
  ProcessConnection (s, msgFromPrompt)

  # Closes the socket.
  s.close()
  s = None
 except Exception as err:
  print ("Socket action failed due to error [" + str(err) + "]")


if __name__ == "__main__":
 main(sys.argv[1:])


Okumak: En İyi Python IDE ve Kod Düzenleyicileri

Diğer Soket Programlama Hususları

Bu temel örneklerle ilgili en büyük potansiyel sorun, soket modülü tarafından herhangi bir şifreleme veya güvenlik sağlanamamasıdır. Şifrelemenin uygulamanın kendisi tarafından sağlanması bekleniyor.

Python soket kodundaki en büyük çekişme kaynaklarından ikisi şunlardır:

  • Soketler yeniden kullanılabilir olacak şekilde yapılandırılmamışsa ( s.setsockopt yöntemi) ve program sonlandırılırsa, program yeniden başlatılıncaya kadar bir dakika kadar bekleme gerekebilir. Bunun nedeni, Linux’un soketin zaman aşımına uğramasını beklemesidir.
  • Bir istemciden gönderilen ve bir sunucudan gönderilen tüm veriler ikili olarak temsil edilmeli ve tutarlı kodlamaya sahip olmalıdır.

Windows’a Özgü Hususlar

Windows bu koda ilişkin kendi değerlendirmelerini sunar. Yeni başlayanlar için, temel sunucu kodunu ilk çalıştırırken, yalnızca aşağıdaki iletişim kutusuyla karşılaşmamakla kalmaz, aynı zamanda onu beklemek ve tıklatmamak zorunludur:

Dullar Güvenlik Duvarı İletişim Kutusu

Şekil 4 – Windows Güvenlik Duvarı İletişim Kutusu

Bu iletişim kutusu iptal edilirse, o zaman hiç Python sunucu uygulaması düzgün çalışmayacak. Daha da kötüsü, istemeden iptal edilirse veya reddedilirse bu iletişim kutusunu geri almanın tek yolu, tüm Windows Güvenlik Duvarı ayarlarını sıfırlamak ve Python sunucu komut dosyasını yeniden çalıştırmaktır.

Windows Komut İstemi kutuları da kendi tuhaflıklarını sunar. Sunucu kodunu çalıştırırken, sunucuyu çalıştıran Komut İstemi kutusunda imleci tıklatmayın veya sürüklemeyin. Bu, sunucunun yazdırmakta olduğu iletileri bastırabilir.

Son olarak, klavye kombinasyonu Ctrl-C veya Ctrl-Ara bir sunucu uygulaması çalıştırılırken Python tarafından yakalanmayabilir. Windows sinyallerini doğrudan kullanmak için uygulamanın yeniden kodlanması gerekebilir veya Windows Komut İstemi kutusu kapatılarak durdurulabilir. İstemcinin gösteriminin sunucuya uygun kapatma komutunu ilettiğini unutmayın.

Ek Python Soket Kaynakları

Python Soket Modülü tam olarak şu adreste belgelenmiştir: https://docs.python.org/3/library/socket.html#module-socket. Python’da soketleri içeren çoğu uygulama, doğrudan soketlerle çalışmayı içermez. Bunun yerine, modüller, otomatik olarak ve geliştiricinin herhangi bir doğrudan katılımı olmaksızın, alt seviye soketlere yapılan tüm çağrılarla ilgilenen daha yüksek seviyeli protokol arayüzlerini uygular. Bu uygulamalar ayrıca diğer güvenlik sorunlarının yanı sıra şifreleme/şifre çözme işlemlerini de otomatik olarak halleder. Daha da ileri giderek, bu sunucu uygulamaları, sunucu yükünü sunucunun birden çok örneği arasında dağıtmak gibi daha karmaşık görevleri yerine getirir.

Bu tür iki örnek, SFTP (Güvenli Dosya Aktarım Protokolü) ve HTTPS (şifreli web istemcisi), temel Python ağ işlemleriyle ilgili bu eğitim dizisinin sonraki bölümünde ele alınacaktır.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.