소켓과 소켓 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

+ Recent posts