[Python]소켓 통신 해보기

Inung_92·2023년 6월 16일
2

Python

목록 보기
1/4
post-thumbnail

포스팅 목적

📖소켓 통신의 기본 개념을 알아보고, 파이썬을 이용하여 서버와 클라이언트 간 기초적인 통신 방법에 대하여 알아보자.

소켓이란?

📖네트워크상에서 가동되는 두 개의 프로그램 간 양방향 통신의 하나의 엔드포인트

소켓은 TCP/IP 기반 네트워크 통신에서 데이터 송수신의 마지막 접점을 이야기한다. 즉, 소켓은 서버와 클라이언트 간 데이터를 주고받는 양방향 연결 지향성 통신을 이야기하는 것이다.

소켓을 사용하기 위해서는 클라이언트와 서버 소켓으로 각각 구분되고, 통신을 하기 위해 IP주소와 포트번호를 이용한다.

위 사진처럼 응용프로그램 계층과 트랜스포트 계층 사이에 논리적으로 위치하여 접점의 역할을 해주는 것이다.

그렇다면 Python을 이용해서 소켓통신을 하는 방법은 어떻게되는지 알아보자.


실습

⚡️소켓의 동작순서

위 사진은 클라이언트와 서버에서 소켓의 동작 순서를 각각 표현한 것이다. 여기서 중요한 부분은 서버에서 liten()을 통해 연결 대기 상태에 진입해야 클라이언트가 해당 소켓을 통해 접속을 할 수 있다.

접속이 성공하면 클라이언트 및 서버는 소켓을 통해 데이터를 주고 받음으로써 통신을 이어나갈 수 있다.

모든 통신을 완료한 이후에는 close()를 통해 연결을 끊어주어야 자원의 낭비를 방지 할 수 있다.

⚡️ 서버 소켓

서버 소켓을 생성하고 통신을 하며, 통신이 완료된 이후에 소켓을 종료하는 것까지의 코드를 작성해보자.

🖥️ socket_server.py

import socket

# 소켓 객체 생성
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 소켓 정보세팅(튜플)
server_address = ('localhost', 9999)
print('Start up on {} port {}'.format(*server_address)

# 소켓 정보 바인딩
server_socket.bind(server_address)

# 소켓 가동
server_socket.listen()

while True:
	print('accept wait')
    # 클라이언트 접속 대기
    client_socket, client_address = server_socket.accept()
    
    try:
    	# 클라이언트가 보낸 데이터 수령(1024byte)
    	data = client_socket.recv(1024)
        # 문자열 치환
        data = data.decode()
        
        ...이후 수행 할 로직 작성
    except Exception as err: # 예외 발생 시
    	# 클라이언트 소켓 연결 끊기
    	client_socket.close()
        break
    finally: # 모든 작업이 종료
    	client_socket.close()
        break

서버의 흐름은 다음과 같다.

소켓 객체 생성 -> 접속 정보 세팅 -> 접속 정보 바인딩 -> 소켓 가동 -> 클라이언트 접속 대기 -> 접속 후 클라이언트 데이터 수령 및 응답 -> 소켓 종료

예시 코드에서 while문에 server_socket.accept()는 동작이 정지된 상태로 대기하기 때문에 아래 코드는 실행되지 않는다. 즉, 클라이언트가 접속을 해야지 반복문의 다음 코드들을 수행하는 것이다.

다음은 클라이언트 코드를 보자.

⚡️ 클라이언트 소켓

생성되어 접속을 기다리는 서버 소켓에 접속해보자.

🖥️ client_socket.py

import socket

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('서버IP', '서버PORT')

# 서버 소켓에 접속
client_socket.connect(server_address)

while True:
	try:
    	# 입력 값
    	data = input('')
        # 입력 값에 특정 문자 식별 시 소켓 종료
        if data == 'quit':
        	break
        data = data.encode()
        client_socket.send(data)

client_socket.close()

기본적으로 클라이언트 코드는 훨씬 간결하고 짧다. 여기서 서버의 응답 메세지를 수령하고 싶다면 아래와 같이 코드를 추가하면 된다.

def recv_message():
	message = client_socket.recv(1024)
    message = message.decode()
    
# 스레드로 실행
start_new_thread(recv_message, (client_socket,))

코드는 상황에 따라 추가 또는 수정해서 사용하면 될 것이다.


마무리

소켓 통신을 이용하여 채팅 등의 프로젝트를 수행하기도 하지만 클라이언트에서 일정한 간격으로 넘어오는 데이터를 가공하여 DB에 저장하는 등의 프로젝트를 구현 할 수도 있다.

이런 경우 신경써야하는 부분은 과연 스레드와 프로세스 중 어떤 것을 통해서 다수의 클라이언트를 받아들이고 컨트롤 할 것인지 고민을 해보아야 한다. 상황에 따라 다르겠지만 나는 이전까지 멀티 스레드에 대해서만 배웠고, 해당 부분을 채팅방 예제를 통해 자바를 사용하여 실습해본 경험이 있다.

하지만 취업을 하고 파이썬을 통해 소켓통신 데몬 토이프로젝트를 수행하다보니 멀티 프로세스의 개념도 알게되었고, 스레드와 프로세스 사용의 차이점에 대해서도 인식을 하게되었다.

자세한 이야기는 다음 포스팅에서 다루겠지만 간단히 정리하면 다음과 같다.

  • 멀티 스레드 중 1개의 스레드가 오류가 발생한다면 해당 프로세스의 스레드는 모두 영향을 받는다.
  • 멀티 프로스세 중 1개의 프로세스가 오류가 발생하면 해당 프로세스만 종료될 뿐 부모 프로세스의 또 다른 자식 프로세스는 지속적으로 구동한다.

다음 게시글에서는 멀티프로세스 소켓 통신을 이용하여 python linux 데몬을 구현하는 과정에 대해서 포스팅 해보고자 한다.

그럼 이만.👊🏽

profile
서핑하는 개발자🏄🏽

0개의 댓글