Metode socket.setblocking() dalam modul bawaan Python socket digunakan untuk mengatur apakah sebuah soket jaringan beroperasi dalam mode blocking (menunggu hingga operasi selesai) atau non-blocking (langsung mengembalikan kontrol atau memicu pengecualian jika data belum siap). Secara default, soket yang baru dibuat diinisialisasi dalam mode blocking.
Ketika soket berada dalam mode blocking, pemanggilan fungsi seperti recv() atau accept() akan membuat eksekusi program berhenti (menunggu) hingga data benar-benar diterima atau ada koneksi yang masuk. Sebaliknya, dalam mode non-blocking, pemanggilan fungsi tersebut akan langsung menghasilkan BlockingIOError (atau EAGAIN / EWOULDBLOCK) jika operasi tidak dapat langsung diselesaikan, memungkinkan program untuk terus menjalankan tugas lain tanpa tertahan.
Sintaks dan Parameter setblocking()
Sintaks dasar untuk menggunakan metode ini sangat sederhana:
sock.setblocking(flag)
Parameter flag menerima nilai boolean:
True: Mengatur soket ke mode blocking (standar).False: Mengatur soket ke mode non-blocking (setara dengan memanggilsock.settimeout(0.0)).
Tabel Perbandingan Mode Blocking vs Non-Blocking
| Fitur / Aspek | Mode Blocking (setblocking(True)) | Mode Non-Blocking (setblocking(False)) |
|---|---|---|
| Perilaku Eksekusi | Program berhenti (menunggu) hingga I/O selesai. | Program langsung lanjut, tidak menunggu I/O. |
| Penggunaan CPU | Rendah saat menunggu, karena thread diblokir oleh OS. | Tinggi jika di dalam infinite loop tanpa jeda (busy waiting). |
| Pengecualian (Exception) | Hanya ralat jaringan umum (misal: koneksi terputus). | Memicu BlockingIOError jika data belum tersedia. |
| Kasus Penggunaan | Aplikasi sederhana, skrip CLI, atau koneksi sinkron. | Server performa tinggi, game loop, atau I/O multipel (async). |
Contoh Implementasi Kode
Berikut adalah contoh implementasi praktis penggunaan setblocking(False) pada sisi klien untuk menghindari program macet (hang) saat mencoba membaca data dari server yang belum siap mengirimkan apa pun:
import socket
import time
# Membuat objek socket TCP/IP
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Menghubungkan ke server lokal pada port 8080
sock.connect(('127.0.0.1', 8080))
# Mengubah socket menjadi non-blocking
sock.setblocking(False)
print("Socket diatur ke mode non-blocking.")
while True:
try:
# Mencoba menerima data
data = sock.recv(1024)
if data:
print(f"Menerima data: {data.decode()}")
break
else:
print("Koneksi ditutup oleh server.")
break
except BlockingIOError:
# Blok ini tereksekusi jika belum ada data yang siap dibaca
print("Belum ada data... melakukan pekerjaan lain.")
time.sleep(1)
finally:
sock.close()
Troubleshooting dan Tips Lapangan
Penggunaan mode non-blocking memerlukan penanganan khusus agar aplikasi tidak mengalami pemborosan sumber daya CPU akibat teknik busy waiting (melakukan pengecekan terus-menerus dalam while loop). Beberapa hal yang perlu diperhatikan:
1. Penanganan Exception yang Tepat: Selalu tangkap BlockingIOError (atau periksa kode error EWOULDBLOCK / EAGAIN) agar aplikasi tidak mendadak crash saat data belum tersedia.
2. Pertimbangkan Modul Selector: Untuk aplikasi produksi skala besar dengan banyak koneksi, hindari pengecekan manual menggunakan loop sederhana. Gunakan modul pustaka standar selectors atau asyncio yang memanfaatkan mekanisme tingkat sistem operasi seperti epoll atau select secara efisien.
3. Relasi dengan settimeout(): Memanggil sock.settimeout(0.0) memiliki efek yang sama persis dengan memanggil sock.setblocking(False). Sebaliknya, memberikan nilai angka positif pada settimeout(5.0) akan mengubah soket kembali ke mode blocking dengan batasan waktu tertentu.