TCP (Transmission Control Protocol)
연결 지향적 : 데이터를 주고받기 전에 연결을 설정(3-way handshake)해서 안정적인 통신 보장.
신뢰성 보장 : 데이터 전송이 성공했는지 확인하고, 손실된 데이터는 재전송.
데이터 순서 보장 : 수신자가 데이터를 전송한 순서대로 받을 수 있도록 조정.
오버헤드 : 오류 제어와 흐름 제어 등으로 인해 처리 비용과 전송 시간이 높음.
사용 사례 : 웹 브라우징(HTTP/HTTPS), 이메일(SMTP, IMAP), 파일 전송(FTP).
UDP (User Datagram Protocol)
비연결 지향적 : 데이터를 보내기 전에 연결 설정을 하지 않아 빠름.
신뢰성 없음: 데이터 전송이 실패하거나 손실돼도 재전송하지 않음.
데이터 순서 보장 없음: 데이터가 순서대로 도착하지 않을 수 있음.
오버헤드 낮음: 단순히 데이터를 전송만 하기 때문에 효율적.
사용 사례: 실시간 스트리밍, 온라인 게임, VoIP 등 빠른 전송이 중요한 경우.
IP 주소
: 인터넷 프로토콜(Internet Protocol)에서 네트워크 상의 장치를 식별하기 위해 사용하는 고유한 주소이다.
: 네트워크 상의 "누구와 통신할지"를 결정하고 인터넷이나 로컬 네트워크에서 장치를 찾는 데 사용한다.
: IPv4 32비트 주소 체계 (예: 192.168.1.1)
: IPv6 128비트 주소 체계 (예: 2001:0db8:85a3:0000:0000:8a2e:0370:7334) - 더 많은 주소 제공
PORT 번호
: 특정 프로세스(프로그램) 또는 서비스와의 통신을 식별하기 위한 숫자이다.
: "어떤 서비스(프로그램)"로 데이터를 보낼지 결정한다.
(IP 주소는 "어디로" 데이터를 보낼지 결정한다.)
: 하나의 IP 주소에서 여러 애플리케이션이 실행될 수 있으므로 이를 구분하는 역할을 한다.
: 0 ~ 65535 (16비트 숫자)
: 0 ~ 1023: 잘 알려진 포트 (HTTP: 80, HTTPS: 443, FTP: 21 등)
: 1024 ~ 49151: 등록된 포트 (특정 애플리케이션 사용)
: 49152 ~ 65535: 동적 / 임시 포트 (클라이언트가 동적으로 할당)
IP 주소와 포트 번호를 합치면 특정 장치의 특정 서비스에 접근 가능하다.
비유하자면 IP주소는 건물 주소 / 포트 번호는 건물 내 특정 방 번호라고 보면 된다.
1) 소켓 생성
: socket.socket()을 호출하여 소켓 객체를 생성한다.
2) IP와 포트를 바인팅
: bind((host, port)) 메서드를 호출해 서버 소켓을 특정 IP와 포트에 연결한다.
3) 대기 상태로 설정 (리스닝)
: listen() 메서드로 서버를 대기상태로 설정한다.
4) 클라이언트 연결 수락
: accept() 메서드를 호출해서 클라이언트의 연결 요청을 수락한다.
5) 데이터 송수신
: recv()과 send()를 사용하여 클라이언트와 데이터 송수신 작업을 진행한다.
6) 소켓 종료
: close() 메서드를 호출해 소켓을 닫는다.
1) 소켓 생성
: socket.socket()을 호출해 클라이언트 소켓 객체를 생성한다.
2) 서버 연결 요청
: connect((host, port)) 메서드로 서버에 연결을 요청한다.
3) 데이터 송수신
: send()와 recv()를 사용해서 연결된 서버와 데이터를 주고 받는다.
4) 소켓 종료
: 작업 완료 후 close() 메서드를 호출해 소켓을 닫는다.
클라이언트 : send() → 서버 : recv() → {서버 : send() 또는 sendall() →} 클라이언트 : recv()
def print_numbers():
for i in range(1, 11):
print(i)
def print_letters():
for letter in 'abcdefghij':
print(letter)
# 두 개의 스레드를 생성하고 시작합니다.
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)
thread1.start()
thread2.start()
import threading
# 숫자를 출력하는 쓰레드 클래스
class NumberPrinter(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print("Sub thread start! ", threading.current_thread().name)
for i in range(1, 11):
print(i)
print("Sub thread end! ", threading.current_thread().name)
# 문자를 출력하는 쓰레드 클래스
class LetterPrinter(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print("Sub thread start! ", threading.current_thread().name)
for letter in 'abcdefghij':
print(letter)
print("Sub thread end! ", threading.current_thread().name)
# 쓰레드 생성 및 실행
number_thread = NumberPrinter("NumberThread")
letter_thread = LetterPrinter("LetterThread")
number_thread.start()
letter_thread.start()
# 메인 스레드가 다른 스레드가 끝날 때까지 대기
number_thread.join()
letter_thread.join()
print("Main thread end!")
프로세스 (Process)
: 실행 중인 프로그램의 독립적인 단위로 CPU와 메모리 같은 시스템 자원을 독립적으로 할당받아 실행된다.
쓰레드 (Thread)
: 프로세스 내에서 실행되는 작업의 세부 단위로 같은 프로세스 내에서 여러 쓰레드가 실행될 수 있다.
세줄요약:
쓰레드란 프로그램안에 또다른 프로그램이다.
소켓이란 네트워크 통신 프로그램을 좀더 쉽게 도와주는 객체 이다.
웹브라우저, 웹서버 , 카카오톡등등 및 네트워 통신을 위한 프로그램은 기본적으로 socket 으로 프로그램을 한다.
