Title: MP4
1MP4
- Implementing TCP reliability mechanisms over UDP
2MP4
- Troll
- RTT and CRC
- Sliding window
- Timers and signal handlers
- General Tips
3Troll Usage
- Simulates different network conditions
- Setup as a intermediate between source and
destination (source sends packet to troll, troll
picks up packet, finds address of destionation,
forwards packet on) - Can be configured (at startup and interactively)
with different parameters - Built on UDP (does not establish connections)
4Troll Usage
- Usage troll options port
- port is where the troll is listening (UDP)
- Start in background -b
- Garble -g ltpercentgt
- Drop -x ltpercentgt
- Reorder -r
- Duplicate -m ltpercentgt
- Delay -s ltmillisecondsgt or se ltmillisecondsgt
(se is exponentially dist.)
5Sample Troll Code for Server
- include ltsys/types.hgt
- include ltnetinet/in.hgt
- include troll.h
- struct sockaddr_in trolladdr, my_addr
- struct hostenet host int troll_sock
- // get troll_host's address info
- if((host gethostbyname(TROLL_HOSTNAME) NULL)
- printf("unknown troll host 's'\n",argv1)
- bzero ((char )trolladdr, sizeof trolladdr)
- trolladdr.sin_family AF_INET
- bcopy(host-gth_addr, (char)trolladdr.sin_addr,
host-gth_length) - trolladdr.sin_port htons(PORT_TROLL_IS_LISTENING
_ON)
6Sample Troll Code for Server
- // create a UDP socket to send/recv from troll
- // PORT_SERVER_IS_LISTENING_ON
- if((troll_sock socket(AF_INET, SOCK_DGRAM, 0))
lt 0) - perror("creating internet UDP socket")
- // get my address info, bind internet UDP sock
and listen for - // messages from troll
- bzero((char )my_addr, sizeof(myaddr))
- localaddr.sin_family AF_INET
- localaddr.sin_addr.s_addr INADDR_ANY // OS
will fill in my IP - localaddr.sin_port PORT_SERVER_IS_LISTENING_ON
- if(bind(troll_sock, (struct sockaddr ) my_addr,
sizeof(my_addr)) lt 0) - perror("internet UDP socket bind")
- / NOTE, server doesnt need to know anything
about client. /
7Sample Troll Code for Client
- include ltsys/types.hgt
- include ltnetinet/in.hgt
- include troll.h
- struct sockaddr_in trolladdr, my_addr,
server_addr - struct hostenet host int troll_sock
- // get troll_host's address info
- if((host gethostbyname(TROLL_HOSTNAME) NULL)
- perror("unknown troll host)
- bzero ((char )trolladdr, sizeof trolladdr)
- trolladdr.sin_family AF_INET
- bcopy(host-gth_addr, (char)trolladdr.sin_addr,
host-gth_length) - trolladdr.sin_port htons(PORT_TROLL_IS_LISTENING
_ON)
8Sample Troll Code for Client
- // create internet UDP sock for sending/receiving
through Troll - if((troll_sock socket(AF_INET, SOCK_DGRAM, 0))
lt 0) - perror("internet UDP socket")
- // bind internet UDP sock and listen for msgs
from Troll - bzero((char ) my_addr, sizeof my_addr)
- my_addr.sin_family AF_INET
- my_addr.sin_addr.s_addr INADDR_ANY // OS will
fill in my IP - my_addr.sin_port PORT_CLIENT_IS_LISTENING_ON
- if(bind(troll_sock, (struct sockaddr ) my_addr,
sizeof my_addr) lt 0) - perror("internet UDP socket bind")
9Sample Troll Code for Client
- // get server addr (but use htons() to get
network type) - if(gethostname(SERVER_HOSTNAME, 30) lt 0)
- perror("getting server hostname")
- if((host gethostbyname(SERVER_HOSTNAME))
NULL) - perror("Unknown host)
- bzero ((char )server_addr, sizeof server_addr)
- server_addr.sin_family htons(AF_INET)
- bcopy(host-gth_addr, (char) server_addr.sin_addr,
host-gth_length) - server_addr.sin_port htons(PORT_SERVER_IS_LISTEN
ING_ON)
10Sample Troll Code for Client
- // in first packet client sends, put server info
inside (must be - // first thing in packet)
- // TROLLPACKET
- typedef struct trollpacket
-
- struct sockaddr_in destaddr
- int type double RTT int seq
- char dataMAX_SIZE
- unsigned CRC
- trollpacket
- trollpacket p
- p.destaddr server_addr // this only needs to
happen once
11Sample Troll Send/Recv Code
- // now packet is ready to be sent...
- char bufsizeof(packet)
- bzero(buf, sizeof(packet))
- bcopy((void )pack, buf, sizeof(packet))
- if(write(troll_sock, buf, sizeof(packet)) lt 0)
- perror(error writing)
- // on receive, packet can just be sent back out
to troll again (same thing happens on server
side) - if(read(troll_sock,buf, sizeof(packet)) lt 0)
- perror(error reading)
- // do something with packet
- if((sendto(troll_sock, buf, sizeof(trollpacket),
0, (struct sockaddr )trolladdr, len)) lt 0) - perror(error writing)
- / NOTE you should be using select() to
determine when a packet is ready to be read
also, since we are only receiving from the Troll,
recvfrom() is not needed /
12gettimeofday() and crc
- include ltsys/time.hgt
- if(gettimeofday((struct timeval )tv, (void
)NULL) lt 0) - perror("gettimeofday")
- double newRTT (double)tv.tv_sec
((double)(tv.tv_usec/(double)1000000)) - include ltcrc.hgt
- trollpacket packet char bufsizeof(trollpacket)
- unsigned check CRC(buf, sizeof(packet))
- // recompute at other side and compare
13Sliding window
- Sliding window behavior in this MP is a
combination of selective repeat and - go-back-N
- Similar to that used in TCP
- Fixed send and receive window size
14Sliding window
- It is similar to go-back-N in that
- ACKs are cumulative
- Client sends duplicate ACKs upon receipt of
out-of-order packets -
15Sliding window
- It is similar to selective repeat in that
- Client buffers out-of-order packets that are
within his receive window - Upon receipt of 3 duplicate ACKs, the server only
retransmits the packet at the low end of his send
window - Upon timeout, the server only retransmits the
packet within his send window corresponding to
the timer that expired
16Sliding window
- Server advances send window as ACKs are received
and sends any new segments that now lie within
send window - Client buffers out-of-order segments that lie
within the receive window and sends duplicate
ACKS indicating the next expected in-order
segment (i.e. the receive window base). Once the
expected in-order segment is received, the
receive window is advanced past in-order segments
and they are written to file.
17Timers and signal handlers
- We need some means of implementing retransmission
timeouts in a non-blocking fashion. - Solution POSIX timers
- Great reference
- http//h30097.www3.hp.com/docs/base_doc/DOCUMENTAT
ION/HTML/APS33DTE_html/DOCU_007.HTM
18Timers and signal handlers
- Two types of timers
- One shot fires only once
- Periodic fires repeatedly at a fixed period
- When a timer expires, the system sends the
specified signal to the process that created the
timer. Thus, you need to set up a signal handler
to catch this signal.
19Timers and signal handlers
- The steps are
- Create and declare a signal handler
- Set the sigevent structure to specify the signal
you want sent on timer expiration - Establish a signal handler with the sigaction
function - Create the timer
20Timers and signal handlers
- timer_create allocates a timer and returns a
timer ID. The timer_create function takes an evp
argument which is a pointer to a sigevent
structure. This structure defines the signal and
value to be sent to the calling process when the
timer expires. Set the sigev_notify member of
evp to SIGEV_SIGNAL. - The timer doesnt start ticking until you call
timer_settime, which sets the expiration values
for the timer.
21Timers and signal handlers
- Structure to define a timer
- // type, sigev_value, sigev_signo ,
it_interval, it_value - struct timer_definition
-
- int type // Absolute or Relative Timer
- struct sigevent evp // Contains signal to be
sent when // timer expires - struct itimerspec timeout // Timer interval
-
- / This struct definition take from
- http//h30097.www3.hp.com/docs/base_doc/DOCUMENTA
TION/HTML/APS33DTE_html/DOCU_007.HTM /
22Timers and signal handlers
- Some declarations
- void sig_handler()
- struct sigaction sig_act
- int clock_id CLOCK_REALTIME
- timer_t periodic_timer_ID, one_shot_timer_ID
- struct timer_definition periodic_timer /
Timer that will expire every 200 ms. / - struct timer_definition one_shot_timer /
one-shot timer /
23Timers and signal handlers
- / Initialize the sigaction structure for the
handler / - sig_act.sa_handler (void )sig_handler
- sig_act.sa_flags 0
- sigemptyset(sig_act.sa_mask)
24Timers and signal handlers
- / Create a one-shot timer to expire in 5 seconds
/ - one_shot_timer.type 0 // relative timer
- one_shot_timer.evp.sigev_value.sival_int
seq_number - one_shot_timer.evp.sigev_signo SIGUSR1
- one_shot_timer.evp.sigev_notify SIGEV_SIGNAL
- one_shot_timer.timeout.it_interval.tv_sec 0
- one_shot_timer.timeout.it_interval.tv_nsec 0
- one_shot_timer.timeout.it_value.tv_sec 5
- one_shot_timer.timeout.it_value.tv_nsec 0
- status timer_create(clock_id,
(one_shot_timer.evp), one_shot_timer_ID) - / Initialize a signal handler to handle timer
expiration / - sigaction(one_shot_timer.evp.sigev_signo,
sig_act, NULL) - / Set time for one-shot timer /
- status timer_settime(one_shot_timer_ID,
one_shot_timer.type, -
(one_shot_timer.timeout), NULL)
25More Tips
- Be careful as to what your CRC is being computed
over (data, header, both?) - Data structures options
- Array of all packets sent, or only a windows
worth of packets - Can be list, queue, array
- Would be helpful to write functions on the data
structure like getOldestUnacked(),
getOldestAckNotSent(), enqueue(), dequeue(),
getPacketBySeq() - Window bounds are getOldestUnacked,getOldestAckNo
tSent-1 - Modularize!
- Send_packet(), Recv_packet(), Wait_for_Packet()
(useful for 3-way handshake, where you are only
waiting for a certain packet)