728x90
소켓 통신이란?
네트워크 상에서 다른 컴퓨터 간 데이터를 주고받기 위한 통신 방식. IP주소와 포트 번호를 사용함
소켓 통신의 흐름
서버 측
1. 소켓 생성: 통신을 위한 소켓을 만듬
2. 바인딩: 소켓에 IP와 포트 연결
3. 리스닝: 클라이언트의 접속 대기
4. 접속 수락: 클라이언트가 접속하면 연결 수락
5. 데이터 송수신: 클라이언트와 데이터 주고 받기
6. 연결 종료
클라이언트 측
1. 소켓 생성
2. 서버에 연결 요청
3. 데이터 송수신
4. 연결 종료
소켓의 종류
TCP 소켓: 연결지향형, 데이터 신회성 높음
UDP 소켓: 비연결지향형, 속도가 빠르지만 신뢰성이 낮음
전송방식에 따른 속도차이
TCP는 데이터를 주고받기 전에 3-way handshake로 연결부터 설정해야함, UDP는 handshake없이 바로 전송
서버
import socket
# 1. 소켓 생성 (IPv4, TCP 소켓)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# - socket.AF_INET: IPv4 주소 체계 사용
# - socket.SOCK_STREAM: TCP 프로토콜 사용
# 2. 바인딩 (IP와 포트 연결)
sock.bind(("", 9999))
# - 빈 문자열("")은 모든 IP 주소에서 접속을 허용한다는 의미 (0.0.0.0)
# - 포트 번호 9999 사용
# 3. 접속 대기 상태 진입
sock.listen()
print("서버 시작")
# - 최대 동시 접속 수는 기본값 (일반적으로 OS에서 설정한 수)
# - listen() 호출 후부터 클라이언트의 접속을 받을 준비 완료
# 4. 클라이언트 접속 수락
conn, addr = sock.accept()
# - 클라이언트가 접속하면 연결을 수락
# - conn: 클라이언트와 데이터를 주고받을 수 있는 소켓 객체
# - addr: 클라이언트의 (IP, 포트) 주소 정보
# 5. 클라이언트로부터 데이터 수신
read_data = conn.recv(1024)
# - 최대 1024바이트까지 데이터를 수신
# - 클라이언트가 보낸 데이터를 바이트로 받아옴
print("recv >>> {}".format(read_data))
# - 수신한 데이터를 출력
# 6. 접속 종료
conn.close() # 클라이언트와의 연결 종료
sock.close() # 서버 소켓 닫기
바이트, 스트링 차이
바이트:
1. 컴퓨터가 처리하는 순수한 이진 데이터
2. 0~255 범위의 숫자 배열
3. 사용 예시: 파일 저장, 네트워크 전송, 암호화 등
스트링:
1. 사람이 읽을 수 있는 문자
2. 유니코드 문자
3. 사용 예시: 화면 출력, 텍스트 데이터 처리
import socket
# 1. 소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 접속시도
sock.connect(("127.0.0.1", 9999))
# 3. 데이터 송신
send_data = input("입력: ")
sock.sendall(bytes(send_data, "utf-8"))
# - 입력받은 문자열을 바이트로 변환하여 서버로 전송
# - utf-8 인코딩을 사용해 문자열을 bytes 타입으로 바꿈
# - sendall(): 모든 바이트가 전송될 때까지 내부적으로 반복 호출
# 4. 접속 종료
print("클라이언트 종료")
sock.close()
에코 서버
에코 서버란?
클라이언트가 보낸 데이터를 그대로 되돌려주는 서버
클라이언트 -> 서버: "Hello"
서버 -> 클라이언트: "Hello"
클라이언트가 보낸 메시지를 서버가 그대로 반사해주는 역할을 함
에코 서버
import socket
# 1. 소켓 생성 (IPv4, TCP 소켓)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# - socket.AF_INET: IPv4 주소 체계 사용
# - socket.SOCK_STREAM: TCP 프로토콜 사용
# 2. 바인딩 (IP와 포트 연결)
sock.bind(("", 9999))
# - 빈 문자열("")은 모든 IP 주소에서 접속을 허용한다는 의미 (0.0.0.0)
# - 포트 번호 9999 사용
# 3. 접속 대기 상태 진입
sock.listen()
print("서버 시작")
# - 최대 동시 접속 수는 기본값 (일반적으로 OS에서 설정한 수)
# - listen() 호출 후부터 클라이언트의 접속을 받을 준비 완료
# 4. 클라이언트 접속 수락
conn, addr = sock.accept()
# - 클라이언트가 접속하면 연결을 수락
# - conn: 클라이언트와 데이터를 주고받을 수 있는 소켓 객체
# - addr: 클라이언트의 (IP, 포트) 주소 정보
# 5-1. 클라이언트로부터 데이터 수신
read_data = conn.recv(1024)
print("recv >>> {}".format(read_data))
# - 최대 1024바이트까지 데이터를 수신
# - 클라이언트가 보낸 데이터를 바이트로 받아옴
# - 수신한 데이터를 출력
# 5-2. 데이터 송신
conn.sendall(read_data)
print("send >>> {}".format(read_data))
# - recv()로 클라이언트가 보낸 메시지를 받고
# - sendall()로 그대로 다시 돌려보냄
# 6. 접속 종료
conn.close() # 클라이언트와의 연결 종료
sock.close() # 서버 소켓 닫기
에코 클라이언트
import socket
# 1. 소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 접속시도
sock.connect(("127.0.0.1", 9999))
# 3-1. 데이터 송신
send_data = input("입력: ")
sock.sendall(bytes(send_data, "utf-8"))
# - 입력받은 문자열을 바이트로 변환하여 서버로 전송
# - utf-8 인코딩을 사용해 문자열을 bytes 타입으로 바꿈
# - sendall(): 모든 바이트가 전송될 때까지 내부적으로 반복 호출
# 3-2. 데이터 수신
recv_data = sock.recv(1024)
print(f"recv : {recv_data}")
# 4. 접속 종료
print("클라이언트 종료")
sock.close()
반복문으로 메시지를 여러번 주고 받음
import socket
# 1. 소켓 생성 (IPv4, TCP 소켓)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# - socket.AF_INET: IPv4 주소 체계 사용
# - socket.SOCK_STREAM: TCP 프로토콜 사용
# 2. 바인딩 (IP와 포트 연결)
sock.bind(("", 9999))
# - 빈 문자열("")은 모든 IP 주소에서 접속을 허용한다는 의미 (0.0.0.0)
# - 포트 번호 9999 사용
# 3. 접속 대기 상태 진입
sock.listen()
print("서버 시작")
# - 최대 동시 접속 수는 기본값 (일반적으로 OS에서 설정한 수)
# - listen() 호출 후부터 클라이언트의 접속을 받을 준비 완료
# 4. 클라이언트 접속 수락
conn, addr = sock.accept()
# - 클라이언트가 접속하면 연결을 수락
# - conn: 클라이언트와 데이터를 주고받을 수 있는 소켓 객체
# - addr: 클라이언트의 (IP, 포트) 주소 정보
while True:
# 5-1. 클라이언트로부터 데이터 수신
read_data = conn.recv(1024)
print("recv >>> {}".format(read_data))
# - 최대 1024바이트까지 데이터를 수신
# - 클라이언트가 보낸 데이터를 바이트로 받아옴
# - 수신한 데이터를 출력
if read_data.decode() == "end":
break
# 5-2. 데이터 송신
conn.sendall(read_data)
print("send >>> {}".format(read_data))
# - recv()로 클라이언트가 보낸 메시지를 받고
# - sendall()로 그대로 다시 돌려보냄
# 6. 접속 종료
print("접속종료")
conn.close() # 클라이언트와의 연결 종료
sock.close() # 서버 소켓 닫기
import socket
# 1. 소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 접속시도
sock.connect(("127.0.0.1", 9999))
while True:
# 3-1. 데이터 송신
send_data = input("입력: ")
sock.sendall(bytes(send_data, "utf-8"))
if send_data == "end":
break
# - 입력받은 문자열을 바이트로 변환하여 서버로 전송
# - utf-8 인코딩을 사용해 문자열을 bytes 타입으로 바꿈
# - sendall(): 모든 바이트가 전송될 때까지 내부적으로 반복 호출
# 3-2. 데이터 수신
recv_data = sock.recv(1024)
print(f"recv : {recv_data}")
# 4. 접속 종료
print("클라이언트 종료")
sock.close()
'정보보안' 카테고리의 다른 글
암호화, 대칭 암호화 (0) | 2025.05.26 |
---|---|
쓰레드를 이용한 소켓 통신 (0) | 2025.05.25 |
스니핑(Sniffing) (0) | 2025.04.20 |
네트워크, 전송 계층 TCP/IP 프로토콜의 연관성 (0) | 2025.04.15 |
HTTP 통신 프로토콜 (1) | 2025.04.11 |