소켓과 소켓 API는 네트워크를 통해 메시지를 보내는 데 사용됩니다. IPC(프로세스 간 통신) 형식을 제공합니다 . 네트워크는 컴퓨터에 대한 논리적 로컬 네트워크이거나 다른 네트워크에 대한 자체 연결을 통해 외부 네트워크에 물리적으로 연결된 네트워크일 수 있습니다. ISP를 통해 연결하는 인터넷을 생각하면 됩니다.
본 문서에서는 다음을 만듭니다.
- 간단한 소켓 서버 및 클라이언트
- 여러 연결 을 동시에 처리하는 개선된 버전
- 완전한 소켓 애플리케이션 처럼 작동하는 서버-클라이언트 애플리케이션
본 문서의 예제에는 Python 3.6 이상이 필요하며 Python 3.10을 사용하여 테스트되었습니다.
소스 코드 가져오기: 여기를 클릭 하여 이 자습서의 예제에 사용할 소스 코드를 다운로드합니다 .
배경
소켓은 오랜 역사를 가지고 있습니다. 1971년 ARPANET 에서 시작되었으며 나중에 Berkeley 소켓 이라고 하는 1983년에 출시된 BSD(Berkeley Software Distribution) 운영 체제의 API가 되었습니다 .
가장 일반적인 유형의 소켓 응용 프로그램은 한쪽이 서버 역할을 하고 클라이언트의 연결을 기다리는 클라이언트-서버 응용 프로그램입니다.
소켓 API 개요
Python의 소켓 모듈은 Berkeley 소켓 API 에 대한 인터페이스를 제공합니다.
이 모듈의 기본 소켓 API 함수 및 메서드는 다음과 같습니다.
- socket()
- .bind()
- .listen()
- .accept()
- .connect()
- .connect_ex()
- .send()
- .recv()
- .close()
Python은 C 대응 시스템인 시스템 호출에 직접 매핑되는 편리하고 일관된 API를 제공합니다.
표준 라이브러리의 일부로 Python에는 이러한 저수준 소켓 기능을 더 쉽게 사용할 수 있는 클래스도 있습니다.또한 HTTP 및 SMTP와 같은 상위 수준 인터넷 프로토콜을 구현하는 많은 모듈이 있습니다.
TCP 소켓
소켓 유형을 socket.SOCK_STREAM로 지정 하여 socket.socket()를 사용하여 소켓 객체를 생성합니다. 이 때 사용되는 기본 프로토콜은 TCP(Transmission Control Protocol) 입니다.
왜 TCP를 사용해야 합니까? 전송 제어 프로토콜(TCP):
- 신뢰할 수 있음: 네트워크에 드롭된 패킷이 발신자에 의해 감지되고 재전송됩니다.
- 순서대로 데이터 전달 있음: 데이터는 발신자가 작성한 순서대로 애플리케이션에서 읽습니다.
대조적으로 로 생성된 UDP(사용자 데이터그램 프로토콜) 소켓 socket.SOCK_DGRAM은 신뢰할 수 없으며 수신자가 읽는 데이터는 보낸 사람의 쓰기 순서가 다를 수 있습니다.
TCP에 대한 소켓 API 호출 및 데이터 흐름의 순서
클라이언트 .connect()는 서버에 대한 연결을 설정하고 3방향 핸드셰이크를 시작하기 위해 호출합니다. 핸드셰이크 단계는 네트워크에서 연결의 각 측면에 도달할 수 있도록 하기 때문에 중요합니다. 즉, 클라이언트가 서버에 도달할 수 있고 그 반대의 경우도 마찬가지입니다. 하나의 호스트, 클라이언트 또는 서버만 다른 호스트에 연결할 수 있습니다.
.send() 와 .recv()에 대한 호출을 사용하여 클라이언트 와 서버 간에 데이터가 교환되는 왕복 섹션이 있습니다.
맨 아래에서 클라이언트와 서버는 각각의 소켓을 닫습니다.
Echo Client and Server
클라이언트와 서버 프로그램을 작성합니다.
클라이언트에게 수신한 내용을 출력하는 서버 프로그램을 작성합니다.
Echo Server
서버 프로그램
# echo-server.py
import socket
HOST = "127.0.0.1" # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print(f"Connected by {addr}")
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
socket.socket()는 컨텍스트 관리자 유형을 지원하는 소켓을 생성하므로 with명령문 에서 사용할 수 있습니다.
s.close() 를 호출할 필요가 없습니다.
.bind()메서드는 소켓을 특정 네트워크 인터페이스 및 포트번호와 연결하는 데 사용됩니다.
서버 예에서 .listen()서버가 연결을 수락할 수 있도록 합니다. 서버를 "수신" 소켓으로 만듭니다.
.accept(). 는 클라이언트와 통신하는 데 사용할 소켓입니다. 서버가 새 연결을 수락하는 데 사용하는 수신 소켓과 다릅니다.
에코 클라이언트
이제 클라이언트를 살펴보겠습니다.
# echo-client.py
import socket
HOST = "127.0.0.1" # The server's hostname or IP address
PORT = 65432 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(b"Hello, world")
data = s.recv(1024)
print(f"Received {data!r}")
.connect()는 소켓 개체를 만들고 서버에 연결하는 데 사용하고, s.sendall()는메시지를 보내기 위해 호출합니다. 마지막으로 s.recv()는 서버의 응답을 읽고 출력하도록 호출합니다 .
에코 클라이언트 및 서버 실행
새로운 터미널 또는 명령 프롬프트를 열고 echo-server.py 스크립트가 포함된 디렉터리로 이동하여 서버를 실행합니다.
$ python echo-server.py
클라이언트 연결을 기다리고 있습니다. 이제 다른 터미널 창이나 명령 프롬프트를 열고 클라이언트를 실행합니다.
$ python echo-client.py
Received b'Hello, world'
서버 창에서 아래 내용을 확인할 수 있습니다.
$ python echo-server.py
Connected by ('127.0.0.1', 64623)
소켓 상태 보기
호스트에서 소켓의 현재 상태를 보려면 netstat를 사용합니다,
다음은 netstat 출력입니다.
$ netstat -an
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp4 0 0 127.0.0.1.65432 *.* LISTEN
'Python' 카테고리의 다른 글
파이썬 - enumerate (0) | 2023.03.29 |
---|---|
Python - Virtual Environments and Packages (0) | 2022.01.06 |
Python - 표준라이브러리 II (0) | 2022.01.06 |
Python - 오류 및 예외 (0) | 2022.01.06 |
Python - 입출력 (0) | 2022.01.06 |