Router는 L3 Switch지만 Host라고도 할 수 있음 (IP도 다 부여, 컴퓨터라고도 할 수 있음)
라우터에 NIC가 여러개 있을 수 있다.
패킷이라는 것이 처리될 때, 라우터 같은 Inline 장치가 어떻게 처리될까?
라우터 내부에서 외부로 통신을 할 때 NIC#1에서 출발하여 IP→TCP→Process→TCP/IP →NIC#2 의 경로를 탈 수 있지만 User모드, Kernel모드, HW를 나누는 경계선을 건널 때마다 waiting 시간이나 CPU를 사용하기 때문에 전산 비용이 비싸진다.
그러므로 NIC#1 ⇒ NIC#2 로 한번에 가도록 하는 HW기반 통신을 하면 ‘가속했다’고 얘기하면서 굉장히 빨라진다.
그런데 NIC#3이 또 있을 수도 있다.
따라서 NIC#1에서 출발하여(=네트워크로 프레임 단위 데이터가 들어와서 패킷 단위로 잘라지든 해서 데이터를 Read했다) IP단에서 처리한 뒤 write를 해야 할 때, NIC#2로 보낼지 NIC#3로 보낼지 인터페이스를 선택을 해야 함
그런데 만약 Read를 했는데 write를 안한다면? 패킷이 필터링되어서 drop이 됨
패킷의 정보를 보고 어디로 보낼지 결정해야 하는데 L3 Switch니까 IP주소를 보고 할 것이다. 그런데 두 개의 NIC 중 적절한 게 없다면 못보내서 Drop되는 경우도 있다.
라우터가 IP단에서 단지처리만 한다면 L3 Switch, Router만이지만, 패킷을 보안적인 측면도 생각해서 처리하면 패킷 단위의 필터링 방화벽이 된다. 필터링을 거쳐서 Bypass 또는 Drop도 하게 되는 것이다.
*Inline 구성이란??
인라인 구성은 모든 트래픽이 해당 보안 장비를 물리적으로 거쳐야만 목적지로 전송될 수 있도록 네트워크를 구성한 것을 말한다.
IP의 역할은 Host to Host만을 지원한다. 하나의 장비 안에서 수많은 프로그램이 통신해야 할 경우는 IP만으로는 한계가 있다
=>프로세스별 구분 지을 수 있는 Port 번호가 등장하게 됨
IP에서 오류가 발생하면 ICMP에서 알려준다. 하지만 알려주기만 할 뿐 대처는 못하므로 상위 프로토콜인 TCP와 UDP가 나오게 됐다
ICMP ? 인터넷 제어 메시지 프로토콜. 네트워크 컴퓨터 위에서 돌아가는 OS에서 오류 메시지를 전송받는데 쓰임
TCP와 UDP의 오류 해결법?
TCP: 데이터의 순차성과 분실, 중복 등을 자동으로 보정해줌으로써 송수신 데이터의 정확한 전달을 보장
UDP: IP가 제공하는 정도의 수준만을 제공하는 간단한 IP 상위 계층의 프로토콜, 확인 응답을 못하므로 TCP와 달리 에러가 날 수 있고 재전송이나 순서가 뒤바뀔 수 있는 번거로움 존재하며 신뢰도 떨어짐
UDP Header
Source Port: 시작 포트
Destination Port: 목적지 포트
Length: 길이
Checksum: 오류 검출
중복 검사의 한 형태로, 오류 정정을 통해 자료의 무결성을 보호하는 단순한 방법
UDP는 왜 사용할까?
데이터의 빠른 처리, 신속성 때문 !!
주로 실시간 방송과 온라인 게임에서 사용됨
네트워크 환경이 안 좋을 때, 끊기는 현상을 생각하자
DNS에서 UDP를 사용하는 이유
DNS Request의 양이 작음 -> UDP Segment에 담길 수 있음
3 way handshaking으로 연결을 유지할 필요가 없음 (TCP는 Protocol Overhead가 큼 )
Request의 손실은 Application layer에서 제어함으로써 신뢰성이 추가될 수 있음 (Timeout이나 재전송 작업을 통해서)
DNS: port 53번
하지만 TCP를 사용하는 경우?
Zone Transfer(=DNS 서버 간의 요청을 주고받을 때 사용하는 transter)를 사용해야 하는 경우!
데이터의 크기가 512바이트(UDP의 제한크기) 를 넘기거나 응답을 못받은 경우
TCP와 UDP 통신 실습
UDP
UDP server 코드
from socket import *
serverName = "192.168.0.108"
serverPort = 12000
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind((serverName, serverPort)) # 12000 포트로 들어오는 프로세스를 소켓에 바인딩print("The server is ready to receive")
whileTrue:
message, clientAddress = serverSocket.recvfrom(2048) # 서버에 들어온 정보를 2kbyte로 계속 읽어들임
modifiedMessages = message.decode().upper() # 읽어드린 바이트 정보를 str로 변환 후 대문자화
serverSocket.sendto(modifiedMessages.encode(), clientAddress) # 클라이언트 목적지 주소도 명시해서 보냄
UDP client 코드
from socket import *
serverName = "192.168.0.108"
serverPort = 12000
clientSocket = socket(AF_INET, SOCK_DGRAM) # UDP의 소켓타입=SOCK_DRGAM
message = input("input lowercase sentence")
clientSocket.sendto(message.encode(), (serverName, serverPort)) # 서버의 IP 주소와 port 번호를 명시해서 서버에게 데이터 요청
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
print(modifiedMessage.decode())
clientSocket.close()
결과
UDP는 비연결형 프로토콜로, 데이터 전송 시에 IP 주소와 port 번호를 명시해줘야 한다.
sendTo() 메서드를 사용
TCP
TCP server 코드
from socket import *
serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(("", serverPort))
serverSocket.listen(1)
print("The server is ready to receive")
whileTrue:
connectionSocket, addr = serverSocket.accept() # 요청을 기다리고 받은 후엔 connection 소켓이라는 새로운 분리된 연결을 만듬
sentence = connectionSocket.recv(1024).decode()
capitalizedSentence = sentence.upper()
connectionSocket.send(capitalizedSentence.encode()) # UDP와 달리 connection이 있으므로 목적지 주소가 필요없음
connectionSocket.close() # 이때 serverSocket은 닫지 않음