Tips on
Network Programming
Understand IPv4 Addressing

Special address


Host ID = 0: network address
Network ID = 0, host ID = 0


127.x.y.z : “looped back”
Host ID = all 1s : broadcasting

NAT address





10/8
172.16/12
192.168/12
Broadcast address

255.255.255.255


IPv4 address는
host의 address 가 아니라
interface의 address이다.
i.e 0.0.0.0 means this network

190.50.255.255



Limited broadcast
router 밖에는 나가지 못함
Network-directed broadcast
그 네트워크까지 가서 네트워크 내에
broadcast
190.50.1.255/24


Subnet-directed broadcast
190.50.1.0/24 subnet 내에 broadcast
Develop and Use Application “Skeletons”



TCP Client, Server 프로그램의 skeleton은
비슷하다.
UDP Client, Server 프로그램의 skeleton도
비슷하다.
다만, 서비스에 따라 내부 로직이 다를 뿐이니
skeleton에서 출발하자.
Build Your Own Library and Use It !


UNP library를 이용하자.
ETCP library도 써먹자.


필요하다면 porting해서 쓰자.
여러분 개인의 library를 만들어 나가자.
Remember that TCP is a Stream Protocol

No message boundary, just a byte stream





TCP application에서 하나의 message를 send()했다고 해서 recevier
application에서 그 message를 한 덩어리로 recv()되는 것이 아니다.
Message를 send()했어도 TCP segment에 언제, 어떻게 실릴지 모른다.
(buffering 되기 때문)
Recv()하면 몇 byte 읽힐지 모른다.
If you want to read exactly n bytes ??
If you want to make a record ???


Use end-of-record mark. e.g) new line
Handle variable records (using fixed header)
메시지를 읽을 user buffer의 크기
즉, 최대로 읽을 수 있는 크기
#include <sys/socket.h> /* UNIX */
#include <winsock2.h>
/* Windows */
int recv (SOCKET s, void *buf, size_t bufsize, int flags);
int read (SOCKET s, void *buf, size_t bufsize);
/* UNIX */
Returns: # of bytes read (>0), 0 if received FIN and no more data, -1 on failure
int send (SOCKET s, const void *buf, size_t len, int flags);
int write (SOCKET s, const void *buf, size_t len);
/* UNIX */
Returns: # of bytes transferred on success, -1 on failure
Socket send buffer에
저장할 메시지 길이
Don’t Underestimate the TCP Performance

TCP는 충분히 Optimize 되어 있다.




통상적인 TCP segment 수신 루틴: 30 instructions
(excluding checksum)
ACK도 piggy-back
섯불리 UDP를 사용하지 말라.
But, a single request-response로 끝나는
transaction에서는 TCP는


Connection set-up: RTT 소요
Connection release: 적어도 RTT 소요
Avoid Reinventing TCP

Any reasonably robust UDP application must provide
Error recovery: reTx a request if not received a response within
RTO
 Sequencing: ensure that replies are matched correctly to
requests
 Flow control: if server’s reply can consist of multiple datagrams,
prohibit overflow of client’s recv buffer
 Cause to rewrite TCP
 TCP는 kernel에서 처리되기 때문에 application에서 reliable
protocol을 구현하는 것보다 실제 빠르다.
UDP를 사용이 권고되는 경우



must be used for broadcast or multicast applications


can be used for simple request-reply applications



desired level of error control must be added
error detection must be needed
Application level에서 real-time control이 필요한 경우 (예: multimedia
streaming)
should not be used for bulk data transfer
TCP is a Reliable Protocol, Not
Infallible Protocol


2 peer간에 connection이 유지되는 한 TCP는 ordered and
uncorrupted delivery를 보장한다.
Application은 통신이 불가능함을 모르고 데이터를 보낼 수 있고,
따라서 목적지에 delivery 되지 못하는 경우가 발생한다.

TCP는 data를 보내봐야 실제 peer TCP와 통신 가능한지 확인 가능
(ACK를 받아 봐야) 또는, 2시간 이상 데이터 교환이 없을 경우에나 통신
불가능을 확인 할 수 있음



교환할 데이터가 없어도 주기적으로 교환해야  heart beat mechanism 구현 필요
Application은 send()/recv()가 error return 되었을 때야, 통신
불가능함을 알게 된다.  failure 처리
통신 불가능한 경우 (실제 connection이 유지되지 않는
경우)



Network outage (due to router or link failure)
Peer app crashes
Peer host crashes
1) Network Outage

Inside TCP



Segment 보낸 후 ACK 가 없으면, 12번 ReTx한다 (약 9분 걸림)
여전히 ACK를 받지 못하면, set socket pending error
(ETIMEOUT)
Inside IP/ICMP
IP datagram을 forwarding할 수 없으면(router나 link 장애로
인해), ICMP host unreachable/network unreachable message를
source로 보낸다.
 이 메시지를 Source IP가 받으면, set socket pending error
(ENETUNREACH/EHOSTUNREACH)
Socket Pending Error






Send() returns on failure  send buffer에 쓰는 것이 실패를 의미
실제 보낸 데이터가 peer에게 전달할 수 없음은 한참 뒤에나 알 수 있다.
Kernel은 이와 같은 error가 발생하면, 해당되는 socket에 pending 시켜
놓는다
Socket API call이 이루어질 때, error return하면서 errno에 설정한다.
2) Peer App Crashes

Peer app crashes(killed)
1.
2.

When peer app crashes,
Local app is

3.
In recv(): return 0


FIN
Call exit(), implicitly
Call close() in exit()
TCP: send FIN
통상적인 절차로 종료
In send(): normal return


But, sent data is lost.
Local connection을 강제
close.
Error is pending.
Send()/recv(): error return
(ECONNRESET)

Send()/recv(): rrror return
(EPIPE)
data
RESET
No connection !
Not delivered to peer app
3) Peer Host Crashes

Local app

Connection set-up

Peer host crash


Send(): normal return



But sent data is lost
Error is pending
(ETIMEOUT) after
retransmitting 12
times(9 min)
or error is pending
(EHOSTUNREACH or
ENETUNREACH) by
ICMP
data
No TCP there, so no
TCP response
No TCP/IP Protocol !
No Notification when Connectivity is lost

데이터를 보내 보지 않고서는 peer와 통신 가능 여부를 알
수 없다


통신 불가능함에도 불구하고 데이터를 보내면 lost됨
(송금했는데 못 받았으면 ???)
데이터 교환과 별도로 상대가 살아 있는지
주기적으로 check해 봐야 함  hearbeat
mechanism 필요

C/S가 여러가지 msg type을 교환하는 경우


Heartbeat msg에 새로운 type을 할당
C/S가 byte stream으로 교환하는 경우



Hearbeat 과 data를 구분할 수 없음
Hearbeat에 대해 별도 TCP connection 설정하여 구분
Or, Hearbeat에 대해 OOB msg로 교환
(send/recv() 에서 flag를 OOB로 설정)
Be Prepared for Rude Behavior from a Peer


Check for client termination
Check for valid input

UNIX utility program 중 6 ~ 43 % 가 인위적으로
생성한 random input으로 시험했을 때 죽었음
Consider Letting inetd Launch Your Application
dup2(sockfd, 0);
dup2(sockfd, 1);
dup2(sockfd, 2);
close(sockfd);
Exec후에 Peer를 알 수 있는 방법은?
Open descriptor들은 fork시 copy되고
Exec 후에도 유지된다.
Consider Using Two TCP Connections

One-connection
architecture


Xout에서 send할 때
pending error는 xin에서
recv해야 알 수 있다
Xin  mp  xout 으로
알려 줘야 함

Two connection
architecture

별도의 connection에 대해
socket pending error가
있는지 testing 가능

Using select() readability