소켓을 이용하여 서버와 클라이언트가 통신을 하는 과정에 대해 공부를 하고 파이썬으로 간단하게 실습을 해보려 한다.
일단 소켓이란 일종의 "문"이다.
애플리케이션 프로세스끼리 통신을 하기 위해 둘 사이를 이어주는 역할을 한다.
우선 소켓 프로그래밍 방식은 TCP 방식과 UDP 방식이 있다.
둘 차이를 간단하게 살펴보자면 TCP 방식은 3-way handshaking을 한다.
- 클라이언트가 서버에게 SYN을 보낸다.
- 서버는 클라이언트에게 연결이 가능하다면 SYN과 ACK를 보낸다.
- 클라이언트가 서버에게 SYN을 보내서 연결 시작을 알린다.
위와 같은 과정을 거치기 때문에 안전하다는 장점이 있다.
UDP는 TCP 처럼 커넥션을 맺는 과정을 거치지 않는다.
커넥션을 맺지 않고 데이터를 보내기 때문에 서버가 데이터를 받을 수 없는 상황이어도 클라이언트는 이를 알 수 없다.
그래서 TCP와 다르게 데이터 손실 가능성이 있어 안정성이 덜하다.
한번 파이썬으로 직접 소켓 프로그래밍을 진행할 예정이다.
클라이언트가 키보드를 통해 값을 입력하면 이 값을 서버에게 보내고 서버에 로그를 남긴다.
서버는 클라이언트에게 "I received 입력값"을 보내서 응답을 잘 받았다고 메시지를 보낸다.
구현하기 쉬운 UDP 방식만 구현해보려 한다. 개발 환경은 visual studio code이다.
UDP 통신 구현
클라이언트부터 살펴보면 클라이언트는 우선 서버의 IP 주소와 포트 번호를 알아야 한다.
우선 자신의 ip 주소부터 확인한다.
cmd 창을 열어서 ipconfig 명령어를 입력한다.
여러가지 내용이 나오는데 우리가 사용할 값은 IPv4 주소이다.
이 값이 우리가 사용할 서버의 IP 주소이다.
통신을 하기 위해서는 IP 주소 이외에도 포트 번호가 필요하다.
임의로 포트 번호를 12000으로 정한다.
이 값을 변수에 저장한다.
from socket import *
ipAddress = 'xxx.xxx.xxx.xxx' #ip 주소
serverPort=15000 #포트 번호
소켓을 생성하고 인풋값을 받는다.
clientSocket = socket(AF_INET, SOCK_DGRAM)
m = input('input : ')
만든 소켓을 사용하여 데이터를 인코딩하여 보낸다. 두 번째 인자로는 ip주소와 포트 번호로 구성된 튜플을 넣어준다.
clientSocket.sendto(m.encode(),(ipAddress, serverPort))
서버가 보낸 응답을 받는다.
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
응답을 출력하고 소켓을 닫는다.
print (modifiedMessage.decode())
clientSocket.close()
<UDP 클라이언트 전체 코드>
from socket import *
ipAddress = 'xxx.xxx.xxx.xxx'
serverPort=15000
clientSocket = socket(AF_INET, SOCK_DGRAM)
m = input('input : ')
clientSocket.sendto(m.encode(),(ipAddress, serverPort))
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
print (modifiedMessage.decode())
clientSocket.close()
이제 서버 차례이다.
서버 소켓을 생성한다.
from socket import *
serverPort = 15000
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('', serverPort))
클라이언트에게 데이터를 받을 때까지 기다린다. 받게되면 받은 메시지를 출력하고 클라이언트에게 잘 받았다는 메시지를 넘겨준다.
while 1:
message, clientAddress = serverSocket.recvfrom(2048)
print("I received"+message.decode())
modifiedMessage = "your message is ".encode()+message
serverSocket.sendto(modifiedMessage, clientAddress)
<UDP 서버 전체 코드>
from socket import *
serverPort = 15000
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('', serverPort))
print ("waiting data")
while 1:
message, clientAddress = serverSocket.recvfrom(2048)
modifiedMessage = "your message is ".encode()+message
serverSocket.sendto(modifiedMessage, clientAddress)
이를 테스트 해보기 위해서 터미널을 두 개 띄운다.
클라이언트와 서버의 파이썬 파일 이름은 각각 socket_c.py와 socket_s.py이다.
터미널에서 python3 socket_c.py와 같은 명령어를 실행해서 서버와 클라이언트 파일을 각각 실행한다.
클라이언트는 입력 값을 기다리고 있다.
서버는 클라이언트로부터 메시지를 기다리고 있다.
입력값을 입력해보면 응답이 제대로 오고 있다.
서버에서도 입력받은 값을 출력하고 있다.
'공부 > Network' 카테고리의 다른 글
[Network] 인터넷 프로토콜 스택 (OSI 7계층 ,TCP/IP 5계층) 및 패킷 전송 과정 (0) | 2023.04.12 |
---|---|
[Network] Transport Layer (다중화/역다중화, TCP가 reliable한 이유) (0) | 2023.04.11 |
[Network] Video Streaming and CDNs (0) | 2023.04.05 |
[Network] P2P applications (0) | 2023.04.03 |
[Network] DNS (0) | 2023.03.27 |
댓글