7. Socket
Socket Programming
Socket: 소켓은 process와 process가 통신하는 end-to-end protocol의 door.
여기서 CPU는 process와 OS를 왔다갔다하며 1 - by - 1 visit을 한다. 즉 매번 네트워크 패킷이 도착했는지 boucing을 하며 체크를 해줘야한다는 것이다.
→ 이 bouncing으로 인해 CPU 성능상의 upperbound가 생긴다. 어떻게 하면 최대속도를 낼 수 있을까?
Dedicate one core in CPU
Network hardware
User space에서 application이 하도록 하자. (ex. cloud computing)
- kernel bypass technique
- 메모리를 왔다갔다 하는 것이 매우 손해이기 때문에, buffer를 많이 크게 만들자.
→ 이렇게 되면 패킷 단위에서는 느려지지만 throughput이 증가한다.
kernel에서 다하게 되면 app까지 안가도 되어서 latency가 줄어든다.
Socket programming에는 2가지 방식이 있다.
- UDP: unreliable datagram
- TCP: reliable, byte stream oriented.
- socket buffer에 패킷을 저장한 다음에, reliable한 order data로 만들어준 후 app으로 올리기 때문에 app 입장에서는 매우 느리다.
UDP
udp는 connection이 없다.
- no handshaking before sending data
- sender explicitly attaches IP address and port #, to each packet
- receiver extracts sender IP address
→ 순서가 뒤바뀔 수 있고, lost될 수 있다.
UDP는 reliable하지 않다. 하지만, n개의 sender에서 한번에 패킷을 받을 수 있다. (useful in P2P!)
반면, TCP는 connection으로 인해 매번 IP주소를 적을 필요가 없다. 단, 1 ACK에 1 RTT가 걸린다.
작동 방식의 차이
- UDP는 ip 주소 붙이고 일단 보냄, datagram 주고 받음
- TCP는 먼저 서버와 contact를 한다.
- socket을 만들고
- 서버와 클라이언트의 socket이 서로 연결된다.
- 서버는 여러 클라를 위해 여러개의 소켓을 만든다.
→ 앱 입장에서는 (virtually) reliable한 연결을 만들어준다.
Latency from socket
Application → socket() → sk_buffer → TCP (Congestion Control Algorithm) → Network device
App에서 buffer로 들어가는 시간 : F(t) → app에 따라 다름
buffer에서 network drive로 들어가는 시간: R(t) → transmit가 끝난 이후에 읽어야하기 때문에 거의 고정됨
따라서 조정할 것은 buffer size임
(1) large: Latency가 증가함.
(2) small: 한번에 조금조금밖에 못보내게 되기 때문에 bitrate가 감소함.
→ Game development: The data has small size (some commands), so F(t) is relatively smaller than R(t). buffer size should be large?
→ zoom : adjust F(t) by R(t) (network)
OS를 매번 거쳐서 네트워크 통신을 처리하면 bouncing 때문에 너무 오래걸린다.
→ priority를 올릴까? 그래도 100% occupy하지는 못한다. 이것이 다 fairness에 대한 문제로 귀결된다.
Transport Layer
그래서 transport layer가 무엇인가.
provide logical communication between app processes
runs in end systems
- break message into segments → 너무 작으면 header 붙이고 떼는 비용이 너무 많이 듦. → 너무 크면 error correction에 불리함. checksum으로는 무슨 패킷이 문제인지 모름. retransmission이 발생할 확률도 큼.
- In analog, there are some bit-switching(flipping) which makes checksum hard to detect error. So, we have to choose appropriate size of packet.
- Lossy channel → small packet size is useful for error correction!
- reassembles segments
- break message into segments → 너무 작으면 header 붙이고 떼는 비용이 너무 많이 듦. → 너무 크면 error correction에 불리함. checksum으로는 무슨 패킷이 문제인지 모름. retransmission이 발생할 확률도 큼.
Network Layer와 뭐가 다른거지?
- Transport : logical communication between
processes
- Network : logical communication between
hosts
편지를 다른 집 아이들에게 보내는 비유를 생각해보면…
transport는 받은 편지를 아이들에게 나눠주는(demux) 부모님들이고
network는 postal service인 것이다.
Multiplexing / Demultiplexing
(1) Multiplexing: 여러 socket에서 받은 데이터를 handle하고, transport header를 붙인다.
(2) Demultiplexing: 받은 여러 데이터으 header를 분석하여 원하는 socket으로 보낸다.
매번 socket으로 데이터를 decode해서 보내야하기 떄문에 에너지 소모가 매우 크다.
→ 즉, sleep이 필요하다.
sender 입장에서는 socket buffer에 패킷이 있을 때 awake하면 된다!
receiver는 100ms마다 wifi로 check하면 될 것이다.
Connectionless demux
같은 ip주소와 port 넘버가 온다면, socket으로 바로바로 보낸다.
즉, 여러 곳에서 온 패킷들이 동시에 마구잡이로 들어올 수 있다.
ex) Youtube에서는 모두 connect해버리면 메모리 오버헤드가 발생한다.
즉, connectionless하게 짜야한다.
→ TCP와 UDP 모두 장단점이 있으니 앱 개발할 때는 적절한 것을 선택해야한다.
Connection-oriented demux
TCP의 소켓은 4개의 tuple로 정의된다. 수신자, 송신자 각각의 ip와 port number
즉, 송신자가 다르면 socket이 다르다. 이것을 여러개의 process로 돌릴 수도 있지만,
보통 threaded server로 처리한다.
UDP usage
- no frills, bare bones (진짜 뼈대라서 필수적인 역할만 수행한다)
- best effort service, but may be lost or out-of-order
- connectionless
- no handshaking
- each UDP handled independently
- smaller header size!
- No Congestion Control → Max data rate
- Used in…
- Streaming multimedia → loss tolerant and rate sensitive
- DNS server → user can easily refresh. Loss is not critical
- SNMP → It exchanges every several minutes
그래도 reliable 해지고 싶다면… → app에서 실행할 것. app에서 recovery할 것!
UDP에는 error를 고치지는 않지만 checksum으로 detect는 할 수 있다.
→ flip 이 2번 발생하면 잡을 수 없음.
Checksum in UDP
모든 16비트를 더한다.
모든 것을 16비트(1 word)로 하여 더하고, carry된 비트를 다시 더해준다.
그 후 1의 보수를 취하여 checksum을 만든다.
→ 해당값을 수신자측에서도 동일하게 적용하여 값을 비교한다.
The Internet checksum will not detect the error?
In which cases, the TCP checksum will not detect an error?
→ 모든 데이터를 16비트로 잘라서 더하기 때문에, 16비트 단위로 값이 서로 flipped되면 checksum은 같아진다.