socket — socket 모듈

이 모듈은 BSD 소켓 인터페이스에 대한 접근을 제공합니다.

CPython과의 차이점

효율성과 일관성을 위해 MicroPython의 소켓 객체는 stream (파일류) 인터페이스를 직접 구현합니다. CPython에서는 makefile() 메서드를 사용하여 소켓을 파일류 객체로 변환해야 합니다. 이 메서드는 MicroPython에서도 여전히 지원되지만(다만 아무 작업도 하지 않음), CPython과의 호환성이 중요한 경우에는 반드시 사용하십시오.

소켓 주소 형식

socket 모듈의 기본 소켓 주소 형식은 getaddrinfo() 함수가 반환하는 불투명 데이터 타입이며, 텍스트 주소(숫자 주소 포함)를 해석하는 데 이 함수를 반드시 사용해야 합니다:

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() 를 사용하는 것이 주소를 다루는 가장 효율적이고(메모리와 처리 능력 측면 모두에서) 이식성 있는 방법입니다.

socket 모듈은 아래에 설명된 대로 튜플을 사용하여 주소를 지정하는 CPython 호환 방식도 제공합니다. OpenMV Cam에서는 socket 모듈이 내장되어 있습니다. 숫자 주소는 튜플 형식으로 직접 지정할 수 있지만, 도메인 이름은 먼저 getaddrinfo() 로 해석해야 합니다.

요약하면:

  • 호스트 이름을 해석할 때는 항상 getaddrinfo() 를 사용하십시오.

  • 아래에 설명된 튜플 주소는 숫자 주소의 단축 표기로, 빠른 해킹이나 대화형 사용에 활용할 수 있습니다.

socket 모듈의 튜플 주소 형식:

  • IPv4: (ipv4_address, port), 여기서 ipv4_address 는 점 표기법의 숫자 IPv4 주소 문자열입니다. 예: "8.8.8.8". port 는 1-65535 범위의 정수 포트 번호입니다. 도메인 이름은 ipv4_address 로 허용되지 않으므로 먼저 getaddrinfo() 를 사용하여 해석하십시오.

  • IPv6: (ipv6_address, port, flowinfo, scopeid), 여기서 ipv6_address 는 콜론 표기법의 숫자 IPv6 주소 문자열입니다. 예: "2001:db8::1". port 는 1-65535 범위의 정수 포트 번호입니다. flowinfo 는 0이어야 합니다. scopeid 는 링크 로컬 주소를 위한 인터페이스 스코프 식별자입니다. 도메인 이름은 ipv6_address 로 허용되지 않으므로 먼저 getaddrinfo() 를 사용하여 해석하십시오.

함수

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

host/port 인수를 해당 서비스에 연결된 소켓을 생성하는 데 필요한 모든 인수를 담은 5-튜플의 시퀀스로 변환합니다. 인수 af, type, proto (이들은 socket 함수에서와 같은 의미를 갖습니다)를 사용하여 반환되는 주소의 종류를 필터링할 수 있습니다. 매개변수를 지정하지 않거나 0으로 두면 모든 주소 조합이 반환될 수 있습니다(사용자 측에서 필터링이 필요함).

결과로 나오는 5-튜플 리스트는 다음과 같은 구조를 가집니다:

(family, type, proto, canonname, sockaddr)

다음 예시는 주어진 url에 연결하는 방법을 보여줍니다:

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])

필터링 매개변수의 권장 사용법:

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과의 차이점

CPython은 이 함수에서 오류가 발생하면 socket.gaierror 예외(OSError 서브클래스)를 발생시킵니다. MicroPython에는 socket.gaierror 가 없으며 OSError를 직접 발생시킵니다. getaddrinfo() 의 오류 번호는 별도의 네임스페이스를 형성하며 errno 모듈의 오류 번호와 일치하지 않을 수 있습니다. getaddrinfo() 오류를 구분하기 위해 이들은 음수로 표현되는 반면, 표준 시스템 오류는 양수입니다(오류 번호는 예외 객체의 e.args[0] 속성으로 접근할 수 있습니다). 음수 값의 사용은 향후 변경될 수 있는 잠정적인 세부 사항입니다.

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

주어진 주소 패밀리 af 의 이진 네트워크 주소 bin_addr 을 텍스트 표현으로 변환합니다:

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

주어진 주소 패밀리 af 의 텍스트 네트워크 주소 txt_addr 을 이진 표현으로 변환합니다:

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

상수

socket.AF_INET: int

IPv4 주소 패밀리.

socket.AF_INET6: int

IPv6 주소 패밀리.

socket.SOCK_STREAM: int

스트림(TCP) 소켓 타입.

socket.SOCK_DGRAM: int

데이터그램(UDP) 소켓 타입.

socket.SOCK_RAW: int

원시 소켓 타입.

socket.IPPROTO_IP: int

IP 프로토콜 수준입니다. IP_* 옵션과 함께 setsockopt()level 인수로 사용됩니다.

socket.IPPROTO_TCP: int

TCP 프로토콜입니다. 이를 socket 에 전달할 필요는 없으며(SOCK_STREAM 소켓 타입이 자동으로 선택함), 유일하게 실질적인 용도는 TCP_* 옵션과 함께 setsockopt()level 인수로 사용하는 것입니다.

socket.SOL_SOCKET: int

소켓 옵션 수준입니다. SO_* 옵션과 함께 setsockopt()level 인수로 사용됩니다.

socket.SO_REUSEADDR: int

여전히 TIME_WAIT 상태에 있는 주소/포트에 소켓을 바인딩할 수 있도록 허용합니다.

socket.SO_BROADCAST: int

브로드캐스트 주소로 데이터그램 전송을 허용합니다.

socket.SO_KEEPALIVE: int

연결된 소켓에서 keep-alive 프로브의 주기적 전송을 활성화합니다.

socket.SO_SNDTIMEO: int

전송 타임아웃(밀리초)이며, setsockopt()value 인수로 전달됩니다.

socket.SO_RCVTIMEO: int

수신 타임아웃(밀리초)이며, setsockopt()value 인수로 전달됩니다.

socket.IP_ADD_MEMBERSHIP: int

멀티캐스트 그룹에 참여합니다. IPPROTO_IP 수준의 setsockopt() 옵션입니다.

socket.IP_DROP_MEMBERSHIP: int

멀티캐스트 그룹에서 탈퇴합니다. IPPROTO_IP 수준의 setsockopt() 옵션입니다.

socket.TCP_NODELAY: int

Nagle 알고리즘을 비활성화합니다. IPPROTO_TCP 수준의 setsockopt() 옵션입니다.

socket.MSG_PEEK: int

recv() / recvfrom() 용: 데이터를 입력 큐에서 제거하지 않고 반환합니다.

socket.MSG_DONTWAIT: int

recv() / recvfrom() 용: 작업을 논블로킹 모드로 수행합니다.

클래스

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

주어진 주소 패밀리, 소켓 타입 및 프로토콜 번호를 사용하여 새 소켓을 생성합니다. 대부분의 경우 proto 를 지정할 필요는 없으며(권장되지도 않음), type 인수가 필요한 프로토콜을 자동으로 선택합니다:

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

소켓을 닫음으로 표시하고 모든 리소스를 해제합니다. 일단 그렇게 되면 소켓 객체에 대한 이후의 모든 작업은 실패합니다. 프로토콜이 지원하는 경우 원격 측은 EOF 표시를 받습니다.

소켓은 가비지 컬렉션될 때 자동으로 닫히지만, 작업을 마치는 즉시 명시적으로 close() 하는 것이 권장됩니다.

bind(address: Any) None

소켓을 address 에 바인딩합니다. 소켓은 아직 바인딩되어 있지 않아야 합니다.

listen(backlog: int = 2) None

서버가 연결을 수락할 수 있게 합니다. backlog 가 지정되면 최소 0이어야 하며(더 작으면 0으로 설정됨), 시스템이 새 연결을 거부하기 전에 허용할 미수락 연결의 수를 지정합니다. 지정하지 않으면 적절한 기본값이 선택됩니다.

accept() Tuple['socket', Tuple]

연결을 수락합니다. 소켓은 주소에 바인딩되어 있고 연결을 수신 대기 중이어야 합니다. 반환 값은 쌍 (conn, address)이며, conn은 해당 연결에서 데이터를 송수신하는 데 사용할 수 있는 새 소켓 객체이고, address는 연결의 반대편 끝에서 소켓에 바인딩된 주소입니다.

connect(address: Any) None

address 에 있는 원격 소켓에 연결합니다.

send(bytes: bytes) int

소켓으로 데이터를 전송합니다. 소켓은 원격 소켓에 연결되어 있어야 합니다. 전송된 바이트 수를 반환하며, 이는 데이터 길이보다 작을 수 있습니다(“short write”).

sendall(bytes: bytes) None

소켓으로 모든 데이터를 전송합니다. 소켓은 원격 소켓에 연결되어 있어야 합니다. send() 와 달리 이 메서드는 데이터를 청크 단위로 연속해서 전송하여 모든 데이터를 전송하려고 시도합니다.

논블로킹 소켓에서 이 메서드의 동작은 정의되어 있지 않습니다. 따라서 MicroPython에서는 대신 write() 메서드를 사용하는 것이 권장되며, 이는 블로킹 소켓에 대해 동일한 “short write 없음” 정책을 가지면서 논블로킹 소켓에서는 전송된 바이트 수를 반환합니다.

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

소켓에서 데이터를 수신합니다. 반환 값은 수신된 데이터를 나타내는 bytes 객체입니다. 한 번에 수신할 수 있는 최대 데이터 양은 bufsize로 지정됩니다.

선택적인 flags 인수는 메시지 플래그(MSG_PEEK, MSG_DONTWAIT)의 비트 OR이며, 이들은 CPython에서와 같은 의미를 가집니다.

sendto(bytes: bytes, address: Any) int

소켓으로 데이터를 전송합니다. 목적지 소켓이 address 로 지정되므로 소켓은 원격 소켓에 연결되어 있지 않아야 합니다.

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

소켓에서 데이터를 수신합니다. 반환 값은 쌍 (bytes, address) 이며, bytes 는 수신된 데이터를 나타내는 bytes 객체이고 address 는 데이터를 전송한 소켓의 주소입니다.

선택적인 flags 인수에 대한 설명은 recv() 함수를 참조하십시오.

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

주어진 소켓 옵션의 값을 설정합니다. 필요한 기호 상수는 socket 모듈에 정의되어 있습니다(SO_* 등). value 는 정수이거나 버퍼를 나타내는 bytes류 객체일 수 있습니다.

settimeout(value: float | None) None

블로킹 소켓 작업에 타임아웃을 설정합니다. value 인수는 초를 나타내는 음이 아닌 부동소수점 수이거나 None일 수 있습니다. 0이 아닌 값이 주어지면, 작업이 완료되기 전에 타임아웃 기간이 경과한 경우 이후의 소켓 작업이 OSError 예외를 발생시킵니다. 0이 주어지면 소켓이 논블로킹 모드로 설정됩니다. None이 주어지면 소켓이 블로킹 모드로 설정됩니다.

이식성 있고 범용적인 대안은 select.poll 객체를 사용하는 것입니다. 이를 통해 여러 객체를 동시에 대기할 수 있습니다(소켓뿐만 아니라 폴링을 지원하는 일반 stream 객체에 대해서도). 예시:

# 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과의 차이점

CPython은 타임아웃의 경우 socket.timeout 예외를 발생시키며, 이는 OSError 서브클래스입니다. MicroPython은 대신 OSError를 직접 발생시킵니다. 예외를 잡기 위해 except OSError: 를 사용하면, 코드가 MicroPython과 CPython 모두에서 동작합니다.

setblocking(flag: bool) None

소켓의 블로킹 또는 논블로킹 모드를 설정합니다. flag가 false이면 소켓이 논블로킹으로, 그렇지 않으면 블로킹 모드로 설정됩니다.

이 메서드는 특정 settimeout() 호출의 단축 표기입니다:

  • sock.setblocking(True)sock.settimeout(None) 과 동일합니다.

  • sock.setblocking(False)sock.settimeout(0) 과 동일합니다.

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

소켓과 연관된 파일 객체를 반환합니다. 정확한 반환 타입은 makefile()에 주어진 인수에 따라 다릅니다. 지원은 이진 모드(‘rb’, ‘wb’, ‘rwb’)로만 제한됩니다. CPython의 인수 encoding, errorsnewline 은 지원되지 않습니다.

CPython과의 차이점

MicroPython은 버퍼링된 스트림을 지원하지 않으므로, buffering 매개변수의 값은 무시되며 0(버퍼링 없음)인 것처럼 취급됩니다.

CPython과의 차이점

makefile()이 반환한 파일 객체를 닫으면 원래 소켓도 함께 닫힙니다.

read(size: int | None = None) bytes

소켓에서 최대 size 바이트를 읽습니다. bytes 객체를 반환합니다. size 가 주어지지 않으면 EOF까지 소켓에서 사용 가능한 모든 데이터를 읽으므로, 소켓이 닫힐 때까지 메서드가 반환되지 않습니다. 이 함수는 요청된 만큼의 데이터를 읽으려고 시도합니다(“short read 없음”). 다만 논블로킹 소켓에서는 이것이 불가능할 수 있으며, 그럴 경우 더 적은 데이터가 반환됩니다.

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

buf 로 바이트를 읽어 들입니다. nbytes 가 지정되면 최대 그만큼의 바이트를 읽습니다. 그렇지 않으면 최대 len(buf) 바이트를 읽습니다. read() 와 마찬가지로 이 메서드는 “short read 없음” 정책을 따릅니다.

반환 값: 읽혀서 buf 에 저장된 바이트 수.

readline() bytes

줄바꿈 문자로 끝나는 한 줄을 읽습니다.

반환 값: 읽은 줄.

write(buf: bytes) int

바이트 버퍼를 소켓에 씁니다. 이 함수는 모든 데이터를 소켓에 쓰려고 시도합니다(“short write 없음”). 다만 논블로킹 소켓에서는 이것이 불가능할 수 있으며, 그럴 경우 반환 값이 buf 의 길이보다 작아집니다.

반환 값: 쓰여진 바이트 수.

참고

MicroPython은 socket.error 를 구현하지 않습니다. CPython에는 OSError 의 별칭인 더 이상 사용되지 않는 socket.error 예외가 있습니다. MicroPython에서는 소켓 관련 오류를 잡기 위해 OSError 를 직접 사용하십시오.