소켓 프로그래밍은 네트워크 통신을 가능하게 해주는 중요한 개념이다. 이때, 블로킹과 논블로킹 소켓은 소켓 작업을 처리하는 방식을 나타내는 두 가지 형태이다. 이 글에서는 블로킹과 논블로킹 소켓의 차이점과 장단점을 알아보고, 파이썬에서의 구현 방법에 대해 살펴보겠다.
블로킹 소켓 (Blocking Socket)
블로킹 소켓은 일반적으로 사용되는 소켓 방식으로, 하나의 작업이 완료될 때까지 다른 작업을 수행하지 않는다. 이는 소켓 작업이 완료되기 전까지 코드의 실행 흐름이 멈추는 것을 의미한다.
블로킹 소켓은 동기적인 방식으로 동작하며, 코드의 실행 흐름을 운영체제에게 일시적으로 양보한다. 예를 들어, 데이터 수신이나 연결 수립을 기다릴 때 소켓 작업이 완료될 때까지 대기한다. 이는 소켓 작업이 오래 걸리거나 대기 시간이 길 때, 프로그램 전체의 성능을 저하시킬 수 있다는 단점이 있다.
import socket
# 블로킹 소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 서버에 연결
sock.connect(('127.0.0.1', 8080))
# 데이터 수신 - 블로킹
data = sock.recv(1024)
print(data)
# 연결 종료
sock.close()
논블로킹 소켓 (Non-blocking Socket)
논블로킹 소켓은 블로킹 소켓과 달리, 소켓 작업이 완료되지 않아도 코드의 실행 흐름이 멈추지 않는다. 이는 소켓 작업이 완료되지 않았을 때에도 다른 작업을 처리할 수 있게 해준다.
논블로킹 소켓은 비동기적인 방식으로 동작하며, 코드의 실행 흐름을 끊지 않고 다른 작업을 수행할 수 있다. 이에 대해서는 주기적으로 소켓 상태를 확인하고 작업이 완료되었는지 여부를 알아내야 한다는 추가적인 로직 구현이 필요하다는 점을 고려해야 한다.
import socket
# 논블로킹 소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(False)
try:
# 서버에 연결 시도
sock.connect(('127.0.0.1', 8080))
except BlockingIOError:
# 연결 시도가 블로킹 되지 않음
# 다른 작업 처리
print("연결 시도 중...")
# 데이터 수신 시도
try:
data = sock.recv(1024)
print(data)
except BlockingIOError:
# 데이터 수신이 블로킹 되지 않음
pass
# 연결 종료
sock.close()
블로킹 vs. 논블로킹 소켓의 장단점
블로킹 소켓 | 논블로킹 소켓 | |
---|---|---|
장점 | 간단하고 직관적인 코드 작성 가능 | 다른 작업과의 동시 처리 가능 |
단점 | 소켓 작업이 완료될 때까지 코드의 실행 흐름이 멈춤 | 소켓 작업 완료 여부 확인하는 추가 로직 필요 |
주로 사용되는 경우 | 소켓 작업이 짧은 시간 동안 완료될 것으로 예상될 때 | 소켓 작업이 오래 걸리거나 대기 시간이 길어질 것으로 예상될 때 |
블로킹 소켓과 논블로킹 소켓은 각각의 특징과 장단점이 있으며, 사용하는 환경과 상황에 따라 선택해야 한다. 단일 작업 처리나 짧은 소켓 작업에는 블로킹 소켓이 유리하며, 여러 작업이 동시에 처리되거나 소켓 작업이 오래 걸릴 것으로 예상될 때에는 논블로킹 소켓을 고려해야 한다.
위에서는 파이썬의 socket
모듈을 사용한 예제 코드를 보여주었으나, 다른 프로그래밍 언어에서도 유사한 개념과 구현 방식이 존재한다. 개발자는 자신이 사용하는 언어와 프레임워크에 맞게 소켓을 구현하고, 블로킹과 논블로킹 방식 중 적합한 방식을 선택해야 한다.