socket — socket modülü

Bu modül, BSD socket arayüzüne erişim sağlar.

CPython ile Farkı

Verimlilik ve tutarlılık açısından, MicroPython’daki socket nesneleri doğrudan bir stream (dosya benzeri) arayüzü uygular. CPython’da bir socket’i makefile() yöntemini kullanarak dosya benzeri bir nesneye dönüştürmeniz gerekir. Bu yöntem MicroPython tarafından hâlâ desteklenir (ancak bir işlem yapmaz), bu nedenle CPython ile uyumluluğun önemli olduğu yerlerde onu kullandığınızdan emin olun.

Socket adres biçim(ler)i

socket modülünün yerel socket adres biçimi, metin biçimli adresleri (sayısal adresler dahil) çözümlemek için kullanılması gereken getaddrinfo() işlevi tarafından döndürülen opak bir veri türüdür:

sockaddr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# You must use getaddrinfo() even for numeric addresses
sockaddr = socket.getaddrinfo('127.0.0.1', 80)[0][-1]
# Now you can use that address
sock.connect(sockaddr)

getaddrinfo() kullanmak, adreslerle çalışmanın (hem bellek hem de işlem gücü açısından) en verimli ve taşınabilir yoludur.

socket modülü ayrıca, aşağıda açıklandığı gibi, demetleri (tuple) kullanarak adres belirtmenin CPython uyumlu bir yolunu da sağlar. OpenMV Cam üzerinde socket modülü yerleşiktir; sayısal adresler doğrudan demet biçiminde verilebilir, ancak alan adlarının önce getaddrinfo() ile çözümlenmesi gerekir.

Özetle:

  • Ana bilgisayar adlarını çözümlemek için her zaman getaddrinfo() kullanın.

  • Aşağıda açıklanan demet adresleri, sayısal adresler için bir kısayol olarak, hızlı denemeler ve etkileşimli kullanım için kullanılabilir.

socket modülü için demet adres biçimi:

  • IPv4: (ipv4_address, port); burada ipv4_address, nokta gösterimli sayısal bir IPv4 adresine sahip bir dizedir, örn. "8.8.8.8" ve port, 1-65535 aralığında bir tamsayı port numarasıdır. Alan adları ipv4_address olarak kabul edilmez; bunları önce getaddrinfo() kullanarak çözümleyin.

  • IPv6: (ipv6_address, port, flowinfo, scopeid); burada ipv6_address, iki nokta gösterimli sayısal bir IPv6 adresine sahip bir dizedir, örn. "2001:db8::1" ve port, 1-65535 aralığında bir tamsayı port numarasıdır. flowinfo 0 olmalıdır. scopeid, bağlantı yerel adresleri için arayüz kapsam tanımlayıcısıdır. Alan adları ipv6_address olarak kabul edilmez; bunları önce getaddrinfo() kullanarak çözümleyin.

İşlevler

socket.getaddrinfo(host: str, port: int, af: int = 0, type: int = 0, proto: int = 0, flags: int = 0, /) List[Tuple]

host/port argümanını, o hizmete bağlı bir socket oluşturmak için gerekli tüm argümanları içeren bir 5-demet (5-tuple) dizisine çevirir. af, type ve proto argümanları (socket işlevindeki ile aynı anlama sahiptir) hangi tür adreslerin döndürüleceğini filtrelemek için kullanılabilir. Bir parametre belirtilmezse veya sıfırsa, adreslerin tüm kombinasyonları döndürülebilir (kullanıcı tarafında filtreleme gerektirir).

Sonuçta elde edilen 5-demet listesi şu yapıya sahiptir:

(family, type, proto, canonname, sockaddr)

Aşağıdaki örnek, belirli bir url’ye nasıl bağlanılacağını gösterir:

s = socket.socket()
# This assumes that if "type" is not specified, an address for
# SOCK_STREAM will be returned, which may be not true
s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1])

Filtreleme parametrelerinin önerilen kullanımı:

s = socket.socket()
# Guaranteed to return an address which can be connect'ed to for
# stream operation.
s.connect(socket.getaddrinfo('www.micropython.org', 80, 0, SOCK_STREAM)[0][-1])

CPython ile Farkı

CPython, bu işlevde bir hata olması durumunda bir socket.gaierror istisnası (OSError alt sınıfı) oluşturur. MicroPython’da socket.gaierror yoktur ve doğrudan OSError oluşturur. getaddrinfo() hata numaralarının ayrı bir ad alanı oluşturduğunu ve errno modülündeki hata numaralarıyla eşleşmeyebileceğini unutmayın. getaddrinfo() hatalarını ayırt etmek için bunlar negatif sayılarla temsil edilirken, standart sistem hataları pozitif sayılardır (hata numaralarına bir istisna nesnesinden e.args[0] özelliği kullanılarak erişilebilir). Negatif değerlerin kullanımı, gelecekte değişebilecek geçici bir ayrıntıdır.

socket.inet_ntop(af: int, bin_addr: bytes) str

Belirtilen af adres ailesine ait ikili bir ağ adresi olan bin_addr öğesini metin temsiline dönüştürür:

>>> socket.inet_ntop(socket.AF_INET, b"\x7f\0\0\1")
'127.0.0.1'
socket.inet_pton(af: int, txt_addr: str) bytes

Belirtilen af adres ailesine ait metin biçimli bir ağ adresi olan txt_addr öğesini ikili temsile dönüştürür:

>>> socket.inet_pton(socket.AF_INET, "1.2.3.4")
b'\x01\x02\x03\x04'

Sabitler

socket.AF_INET: int

IPv4 adres ailesi.

socket.AF_INET6: int

IPv6 adres ailesi.

socket.SOCK_STREAM: int

Akış (TCP) socket türü.

socket.SOCK_DGRAM: int

Datagram (UDP) socket türü.

socket.SOCK_RAW: int

Ham socket türü.

socket.IPPROTO_IP: int

IP protokol düzeyi. IP_* seçenekleriyle birlikte setsockopt() öğesine level argümanı olarak kullanılır.

socket.IPPROTO_TCP: int

TCP protokolü. Bunu socket öğesine iletmeniz gerekmez (SOCK_STREAM socket türü onu otomatik olarak seçer); tek gerçek kullanımı, TCP_* seçenekleriyle birlikte setsockopt() öğesine level argümanı olmasıdır.

socket.SOL_SOCKET: int

Socket seçeneği düzeyi. SO_* seçenekleriyle birlikte setsockopt() öğesine level argümanı olarak kullanılır.

socket.SO_REUSEADDR: int

Socket’in hâlâ TIME_WAIT durumunda olan bir adrese/porta bağlanmasına izin verir.

socket.SO_BROADCAST: int

Bir yayın (broadcast) adresine datagram gönderilmesine izin verir.

socket.SO_KEEPALIVE: int

Bağlı bir socket üzerinde keep-alive yoklamalarının periyodik olarak iletilmesini etkinleştirir.

socket.SO_SNDTIMEO: int

Gönderme zaman aşımı, milisaniye cinsinden, setsockopt() öğesine value argümanı olarak iletilir.

socket.SO_RCVTIMEO: int

Alma zaman aşımı, milisaniye cinsinden, setsockopt() öğesine value argümanı olarak iletilir.

socket.IP_ADD_MEMBERSHIP: int

Bir çoklu yayın (multicast) grubuna katılır. IPPROTO_IP düzeyinde bir setsockopt() seçeneği.

socket.IP_DROP_MEMBERSHIP: int

Bir çoklu yayın (multicast) grubundan ayrılır. IPPROTO_IP düzeyinde bir setsockopt() seçeneği.

socket.TCP_NODELAY: int

Nagle algoritmasını devre dışı bırakır. IPPROTO_TCP düzeyinde bir setsockopt() seçeneği.

socket.MSG_PEEK: int

recv() / recvfrom() için: veriyi giriş kuyruğundan kaldırmadan döndürür.

socket.MSG_DONTWAIT: int

recv() / recvfrom() için: işlemi engellemesiz (non-blocking) modda gerçekleştirir.

Sınıflar

class socket.socket(af: int = AF_INET, type: int = SOCK_STREAM, proto: int = IPPROTO_TCP, /)

Verilen adres ailesi, socket türü ve protokol numarasını kullanarak yeni bir socket oluşturur. proto belirtmek çoğu durumda gerekli değildir (ve önerilmez); type argümanı gereken protokolü otomatik olarak seçer:

# Create STREAM TCP socket
socket(AF_INET, SOCK_STREAM)
# Create DGRAM UDP socket
socket(AF_INET, SOCK_DGRAM)
close() None

Socket’i kapalı olarak işaretler ve tüm kaynakları serbest bırakır. Bu gerçekleştikten sonra, socket nesnesi üzerindeki gelecekteki tüm işlemler başarısız olur. Protokol tarafından destekleniyorsa, uzaktaki uç EOF bildirimi alır.

Socket’ler çöp toplama (garbage collection) sırasında otomatik olarak kapatılır, ancak onlarla çalışmayı bitirir bitirmez açıkça close() ile kapatmanız önerilir.

bind(address: Any) None

Socket’i address öğesine bağlar. Socket halihazırda bağlı olmamalıdır.

listen(backlog: int = 2) None

Bir sunucunun bağlantıları kabul etmesini etkinleştirir. backlog belirtilirse en az 0 olmalıdır (daha düşükse 0’a ayarlanır) ve sistemin yeni bağlantıları reddetmeden önce izin vereceği kabul edilmemiş bağlantı sayısını belirtir. Belirtilmezse, makul bir varsayılan değer seçilir.

accept() Tuple['socket', Tuple]

Bir bağlantıyı kabul eder. Socket bir adrese bağlı olmalı ve bağlantıları dinliyor olmalıdır. Dönüş değeri bir (conn, address) çiftidir; burada conn, bağlantı üzerinde veri gönderip almak için kullanılabilen yeni bir socket nesnesi ve address, bağlantının diğer ucundaki socket’e bağlı adrestir.

connect(address: Any) None

address adresindeki uzak bir socket’e bağlanır.

send(bytes: bytes) int

Socket’e veri gönderir. Socket uzak bir socket’e bağlı olmalıdır. Gönderilen bayt sayısını döndürür; bu, verinin uzunluğundan küçük olabilir (“kısa yazma”).

sendall(bytes: bytes) None

Tüm veriyi socket’e gönderir. Socket uzak bir socket’e bağlı olmalıdır. send() yönteminin aksine, bu yöntem veriyi ardışık olarak parça parça göndererek tüm veriyi göndermeye çalışır.

Bu yöntemin engellemesiz socket’lerdeki davranışı tanımsızdır. Bu nedenle MicroPython’da, engelleyici socket’ler için aynı “kısa yazma yok” politikasına sahip olan ve engellemesiz socket’lerde gönderilen bayt sayısını döndüren write() yöntemini kullanmanız önerilir.

recv(bufsize: int, flags: int = 0) bytes

Socket’ten veri alır. Dönüş değeri, alınan veriyi temsil eden bir bytes nesnesidir. Bir seferde alınacak azami veri miktarı bufsize ile belirtilir.

İsteğe bağlı flags argümanı, CPython’daki ile aynı anlama sahip olan mesaj bayraklarının (MSG_PEEK, MSG_DONTWAIT) bit düzeyinde VEYA işlemidir.

sendto(bytes: bytes, address: Any) int

Socket’e veri gönderir. Hedef socket address tarafından belirtildiğinden, socket uzak bir socket’e bağlı olmamalıdır.

recvfrom(bufsize: int, flags: int = 0) Tuple[bytes, Tuple]

Socket’ten veri alır. Dönüş değeri bir (bytes, address) çiftidir; burada bytes, alınan veriyi temsil eden bir bytes nesnesi ve address, veriyi gönderen socket’in adresidir.

İsteğe bağlı flags argümanının açıklaması için recv() işlevine bakın.

setsockopt(level: int, optname: int, value: int | bytes) None

Verilen socket seçeneğinin değerini ayarlar. Gerekli sembolik sabitler socket modülünde tanımlanmıştır (SO_* vb.). value, bir tamsayı veya bir arabelleği temsil eden bytes benzeri bir nesne olabilir.

settimeout(value: float | None) None

Engelleyici socket işlemleri üzerinde bir zaman aşımı ayarlar. value argümanı, saniye ifade eden negatif olmayan bir kayan noktalı sayı veya None olabilir. Sıfırdan farklı bir değer verilirse, sonraki socket işlemleri, işlem tamamlanmadan önce zaman aşımı süresi dolarsa bir OSError istisnası oluşturur. Sıfır verilirse, socket engellemesiz moda alınır. None verilirse, socket engelleyici moda alınır.

Taşınabilir ve genel bir alternatif, bir select.poll nesnesi kullanmaktır. Bu, aynı anda birden çok nesne üzerinde (yalnızca socket’ler değil, yoklamayı destekleyen genel stream nesneleri üzerinde) beklemeye olanak tanır. Örnek:

# Instead of:
s.settimeout(1.0)  # time in seconds
s.read(10)  # may timeout

# Use:
poller = select.poll()
poller.register(s, select.POLLIN)
res = poller.poll(1000)  # time in milliseconds
if not res:
    # s is still not ready for input, i.e. operation timed out

CPython ile Farkı

CPython, zaman aşımı durumunda, bir OSError alt sınıfı olan bir socket.timeout istisnası oluşturur. MicroPython bunun yerine doğrudan bir OSError oluşturur. İstisnayı yakalamak için except OSError: kullanırsanız, kodunuz hem MicroPython’da hem de CPython’da çalışır.

setblocking(flag: bool) None

Socket’in engelleyici veya engellemesiz modunu ayarlar: flag false ise socket engellemesiz moda, aksi takdirde engelleyici moda alınır.

Bu yöntem, belirli settimeout() çağrıları için bir kısayoldur:

  • sock.setblocking(True), sock.settimeout(None) ile eşdeğerdir

  • sock.setblocking(False), sock.settimeout(0) ile eşdeğerdir

makefile(mode: str = 'rb', buffering: int = 0, /) Any

Socket ile ilişkili bir dosya nesnesi döndürür. Döndürülen tam tür, makefile() öğesine verilen argümanlara bağlıdır. Destek yalnızca ikili modlarla (‘rb’, ‘wb’ ve ‘rwb’) sınırlıdır. CPython’un argümanları olan encoding, errors ve newline desteklenmez.

CPython ile Farkı

MicroPython arabelleğe alınmış akışları desteklemediğinden, buffering parametresinin değerleri yok sayılır ve 0 (arabelleğe alınmamış) gibi işlenir.

CPython ile Farkı

makefile() tarafından döndürülen dosya nesnesinin kapatılması, orijinal socket’i DE kapatır.

read(size: int | None = None) bytes

Socket’ten en fazla size bayt okur. Bir bytes nesnesi döndürür. size verilmezse, socket’ten EOF’a kadar mevcut tüm veriyi okur; bu nedenle yöntem, socket kapatılana kadar dönmez. Bu işlev, istenen kadar çok veriyi okumaya çalışır (“kısa okuma yok”). Bununla birlikte, engellemesiz bir socket’te bu mümkün olmayabilir ve o zaman daha az veri döndürülür.

readinto(buf: bytearray | memoryview, nbytes: int | None = None) int

buf içine bayt okur. nbytes belirtilirse en fazla o kadar bayt okunur. Aksi takdirde en fazla len(buf) bayt okunur. Tıpkı read() gibi, bu yöntem de “kısa okuma yok” politikasını izler.

Dönüş değeri: okunan ve buf içine depolanan bayt sayısı.

readline() bytes

Bir satır sonu karakteriyle biten bir satır okur.

Dönüş değeri: okunan satır.

write(buf: bytes) int

Bayt arabelleğini socket’e yazar. Bu işlev, tüm veriyi bir socket’e yazmaya çalışır (“kısa yazma yok”). Bununla birlikte, engellemesiz bir socket’te bu mümkün olmayabilir ve döndürülen değer buf uzunluğundan küçük olur.

Dönüş değeri: yazılan bayt sayısı.

Not

MicroPython socket.error öğesini uygulamaz. CPython’da, OSError öğesinin bir takma adı olan, kullanımdan kaldırılmış bir socket.error istisnası vardır; MicroPython’da, socket ile ilgili hataları yakalamak için doğrudan OSError kullanın.