Giriş

Python'da ağ programlama yaparken karşılaşılan yaygın hatalardan biri ConnectionResetError hatasıdır. Bu hata, bir TCP bağlantısının beklenmedik şekilde sıfırlanması (reset) durumunda ortaya çıkar. Bu makalede, ConnectionResetError'ın ne olduğunu, nedenlerini ve nasıl çözüleceğini detaylı bir şekilde ele alacağız.


ConnectionResetError Nedir?

ConnectionResetError, Python'da bir ağ bağlantısı sırasında uzak sunucunun bağlantıyı aniden kesmesi veya sıfırlaması durumunda ortaya çıkan bir istisnadır (exception). Bu hata genellikle socket programming veya HTTP istekleri (requests, urllib, aiohttp gibi kütüphaneler) sırasında görülür.

Hatanın tipik görünümü şöyledir:

python
ConnectionResetError: [Errno 104] Connection reset by peer

veya Windows'ta:

python
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

ConnectionResetError'ın Nedenleri

Bu hatanın birkaç temel nedeni vardır:

1. Uzak Sunucunun Bağlantıyı Kesmesi

  • Sunucu, istemciyle olan bağlantıyı aniden sonlandırabilir.

  • Örnek: Bir HTTP sunucusu, uzun süre yanıt vermeyen bir bağlantıyı kapatabilir.

2. Ağ Sorunları

  • İnternet bağlantısının kesilmesi.

  • Firewall veya güvenlik duvarı engellemeleri.

3. Yanlış Socket Kullanımı

  • Bir socket bağlantısı kapatıldıktan sonra tekrar kullanılmaya çalışılırsa.

  • Veri gönderimi sırasında bağlantının kopması.

4. TCP Keep-Alive Mekanizmasının Eksikliği

  • Uzun süreli bağlantılarda TCP Keep-Alive paketleri gönderilmezse, bağlantı zaman aşımına uğrayabilir.

5. Sunucu Tarafında Hata Oluşması

  • Sunucu çöktüğünde veya yeniden başlatıldığında bağlantı resetlenebilir.


ConnectionResetError Nasıl Çözülür?

Bu hatayı çözmek için çeşitli yöntemler mevcuttur:

1. Yeniden Deneme Mekanizması (Retry)

Hata oluştuğunda bağlantıyı yeniden denemek için bir retry mekanizması kullanılabilir.

Örnek Kod:

python
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

def get_with_retry(url):
    session = requests.Session()
    retry = Retry(
        total=3,  # Maksimum 3 deneme
        backoff_factor=1,  # Bekleme süresi artışı
        status_forcelist=[500, 502, 503, 504, 104]
    )
    adapter = HTTPAdapter(max_retries=retry)
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    
    try:
        response = session.get(url)
        return response.text
    except Exception as e:
        print(f"Hata oluştu: {e}")
        return None

print(get_with_retry("https://example.com"))

2. Socket Bağlantısını Doğru Kapatma

Socket kullanırken bağlantıyı doğru şekilde kapatmak önemlidir.

Örnek Kod:

python
import socket

def send_data(data):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(("example.com", 80))
        s.sendall(data.encode())
        response = s.recv(1024)
        print(response.decode())
    except ConnectionResetError as e:
        print(f"Bağlantı sıfırlandı: {e}")
    finally:
        s.close()  # Socketi kapat

3. TCP Keep-Alive Ayarlarını Yapılandırma

Uzun süreli bağlantılarda TCP Keep-Alive ayarlarını etkinleştirebilirsiniz.

Örnek Kod:

python
import socket

def set_keepalive(sock, after_idle_sec=60, interval_sec=30, max_fails=5):
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, after_idle_sec)
    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec)
    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
set_keepalive(s)
s.connect(("example.com", 80))

4. Zaman Aşımı (Timeout) Ayarlama

Bağlantı ve okuma işlemleri için zaman aşımı belirlemek, beklenmedik hataları önler.

Örnek Kod:

python
import requests

try:
    response = requests.get("https://example.com", timeout=10)  # 10 saniye timeout
    print(response.text)
except requests.exceptions.RequestException as e:
    print(f"İstek hatası: {e}")

5. Proxy ve Firewall Ayarlarını Kontrol Etme

  • Proxy kullanılıyorsa doğru yapılandırıldığından emin olun.

  • Firewall'ın bağlantıyı engellemediğini kontrol edin.


Örnek Senaryolar ve Çözümleri

1. HTTP İsteklerinde ConnectionResetError

Sorun: requests kütüphanesi ile bir API'ye istek atarken bağlantı resetleniyor.

Çözüm:

python
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

session = requests.Session()
retry = Retry(total=3, backoff_factor=1)
adapter = HTTPAdapter(max_retries=retry)
session.mount("http://", adapter)
session.mount("https://", adapter)

try:
    response = session.get("https://api.example.com/data", timeout=10)
    print(response.json())
except requests.exceptions.RequestException as e:
    print(f"İstek başarısız: {e}")

2. Socket Programlamada Bağlantı Kopması

Sorun: Socket üzerinden veri gönderirken bağlantı kopuyor.

Çözüm:

python
import socket

def send_data_with_retry(data, host="example.com", port=80, max_retries=3):
    for attempt in range(max_retries):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(10)  # 10 saniye timeout
            s.connect((host, port))
            s.sendall(data.encode())
            response = s.recv(1024)
            print(f"Yanıt: {response.decode()}")
            return
        except (ConnectionResetError, socket.timeout) as e:
            print(f"Deneme {attempt + 1} başarısız: {e}")
        finally:
            s.close()
    print("Maksimum deneme sayısı aşıldı.")

send_data_with_retry("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")

Sonuç

ConnectionResetError, Python'da ağ işlemleri sırasında sık karşılaşılan bir hatadır. Bu makalede, hatanın nedenlerini ve çözüm yöntemlerini detaylı bir şekilde inceledik. Yeniden deneme mekanizmaları, zaman aşımı ayarları, TCP Keep-Alive ve doğru socket kullanımı gibi yöntemlerle bu sorunu çözebilirsiniz.

Eğer bu hata ile sık karşılaşıyorsanız:

  1. Sunucu tarafını kontrol edin.

  2. Ağ bağlantısını test edin.

  3. Kodunuzda retry ve timeout mekanizmaları ekleyin.

Bu adımları uygulayarak ConnectionResetError sorunlarını minimize edebilirsiniz.


Sık Sorulan Sorular (SSS)

1. ConnectionResetError ile ConnectionAbortedError arasındaki fark nedir?

  • ConnectionResetError: Bağlantı uzak sunucu tarafından sıfırlandı.

  • ConnectionAbortedError: Bağlantı yerel sistem tarafından iptal edildi.

2. Bu hata neden SSL bağlantılarında olur?

SSL sertifikası geçersizse veya sunucu TLS bağlantısını keserse bu hata oluşabilir.

3. Bu hatayı tamamen engellemek mümkün mü?

Hayır, ancak retry mekanizmaları ve doğru ağ yönetimi ile minimize edilebilir.