420 likes | 615 Views
Reliable Data Transfer Protocol. IMPLEMENTATION TIPS. Recall. application. application. writes data. reads data. socket. socket. door. door. TCP. TCP. send buffer. receive buffer. Packet ->. Reliable Data Transfer Mechanisms: Checksum Timer Sequence number ACK NAK
E N D
Reliable Data Transfer Protocol IMPLEMENTATION TIPS
Recall application application writes data reads data socket socket door door TCP TCP send buffer receive buffer Packet -> • Reliable Data Transfer Mechanisms: • Checksum • Timer • Sequence number • ACK • NAK • Window, pipelining - Verification of integrity of packet - Signals necessary re-transmission is required - Keeps track of which packet has been sent and received - Indicates receipt of packet in good or bad form - Allows for the sending of multiple yet-to-be-acknowledged packets
Client - Server Rclient_UDP.cpp Rserver_UDP.cpp CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... Empty . . . socket socket UDP (User Datagram Protocol) • – has no connection establishment • No connection state at servers • less packet overhead than TCP • light error-checking (checksum) • server doesn’t use the listen() function • server doesn’t use the accept() function
UDP Basics • See Lecture-2012-6-Socket Programming-Part2(Slide #4)
Client - Server Rclient_UDP.cpp Rserver_UDP.cpp CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... Empty . . . socket socket Port: 1235 Sample run: Rclient 127.0.0.1 1235 0 0 Rserver1235 0 0 Bits can be corrupted Packets can be lost You should run the server first, before running the client. You can test your client and server using the same machine by using the example run above.
Client - Server Rclient_UDP.cpp Rserver_UDP.cpp CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... Empty . . . socket socket Rclient 127.0.0.1 1235 0 0 Rserver1235 0 0 The client is the sender, while the server is the receiver. The filenames used for sending and saving have been fixed in the start-up codes (i.e. File1_Windows.txt, File1_Saved.txt).
Client - Server Rclient_UDP.cpp Rserver_UDP.cpp CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... Empty . . . socket socket Rclient 127.0.0.1 1235 0 0 Rserver1235 0 0 The client sends the contents of the file line by line. One packet contains exactly one line. In order to implement reliable data transfer, you will have to modify the packet header to add more details.
Client - Server Rclient_UDP.cpp Rserver_UDP.cpp CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... Empty . . . socket socket Rclient 127.0.0.1 1235 0 0 Rserver1235 0 0 The objective is for you to implement a reliable data transfer protocol. You can choose to implement a simple stop-and-wait protocol or any of the pipe-lining protocols (i.e. Go Back-N, Selective Repeat).
Client - Server Rclient_UDP.cpp Rserver_UDP.cpp APPLICATION LAYER CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... socket socket Reads file, then sends the contents 1 line at a time Receives file contents line-by-line, then stores everything into a file TRANSPORT LAYER UNRELIABLE CHANNEL NETWORK LAYER
Client - Server Rclient_UDP.cpp Rserver_UDP.cpp APPLICATION LAYER CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... socket socket Reads file, then sends the contents 1 line at a time Receives file contents line-by-line, then stores everything into a file TRANSPORT LAYER UNRELIABLE CHANNEL Simulated by a function named send_unreliably() NETWORK LAYER
Unreliable Channel Simulation intsend_unreliably( ints, char * send_buffer, structsockaddr_inremoteaddress) { int fate=packets_fate(); //random number generator: 0, 1, 2 if (fate==0){ //no problem will be introduced bytes = sendto(s, send_buffer, ...) printf("<-- SEND: %s \n",send_buffer); } else if (fate== 1){ // introduce corrupted bits send_buffer[damage_bit()]=random_char(); send_buffer[damage_bit()]=random_char(); bytes = sendto(s, send_buffer, ...) printf("<-- DAMAGED %s \n",send_buffer); … } else if(fate==2){ // lose the packet printf("X-- LOST %s \n",send_buffer); } } You are not allowed to modify this function in the assignment.
UDP segment structure • The optional parameters are not even included in the sendto() function. Optional in IPv4 intsendto( SOCKET s, char *buf, intmsglen, intflags, structsockaddr *to, inttolen ); • The O/S will automatically provide the IP address of the sender of the segment.
sendto() • Send data through a socket: sendto(SOCKET s, char *msg, int msglen, int flags, structsockaddr *to, int *tolen); PARAMETERS s = socket (inside the socket descriptor: port and IP address...) msg = a pointer to a buffer (could be a string) msglen = the length of the buffer flags = 0 (forget about them for this exercise...) to=structure of address with the IP / port # tolen=length of the structure Example: sendto(s, sbuffer, strlen(sbuffer),0,(structsockaddr*) to, &len);
recvfrom() • Receive data int recvfrom(SOCKET s, char *msg, int msglen, int flags, structsockaddr *from, int *fromlen) PARAMETERS s = socket (inside the socket descriptor: port and IP address...) msg = a pointer to a buffer msglen = the length of the buffer flags = 0 from =structure of address with the IP / port # fromlen=length of the structure Example: recvfrom(s, rbuffer, 1, 0,(structsockaddr *) &from, &len);
Client - Server Rclient_UDP.cpp Rserver_UDP.cpp CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... socket socket Reads file, then sends the contents 1 line at a time Receives file contents line-by-line, then stores into a file UDP SEGMENT Destination Port: 1235 checksum Length of segment DATA
Client - Server Rclient_UDP.cpp Rserver_UDP.cpp CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... socket socket Reads file, then sends the contents 1 line at a time Receives file contents line-by-line, then stores into a file Destination Port: 1235 checksum Length of segment DATA CRC_NUM PACKET 0 0 ABCDEF ‘\r’ ‘\n’ User-defined
Start-up Codes (Client-Server)
CRC Let’s have a look at the CRC function provided as part of the start-up codes and the CRC test program.
Socket(in non-blocking mode) //******************************************************************* // CREATE CLIENT'S SOCKET //******************************************************************* s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { printf("socket failed\n"); WSACleanup(); exit(1); } //nonblocking option u_longiMode=1; ioctlsocket(s, FIONBIO, &iMode); • We need to set our socket in non-blocking mode of operation. • This prevents the recvfrom() function from stopping and waiting for a packet. • Remember, packets could be lost in our simulation of the unreliable channel.
Start-up Codes (Client – Server) Rclient_UDP.cpp Rserver_UDP.cpp CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... socket socket Reads file using fgets(), then sends the contents 1 line at a time Receives file contents line-by-line, then stores into a file fopen(“file1_Windows.txt”, r) fopen(“file1_Saved”, w) Loop: recvfrom() send_unreliably(ACK) Loop: send_unreliably(data) recvfrom()
Reading the file contents CLIENT • The client reads the file contents line by line using fgets() • fgets(send_buffer, SEGMENT_SIZE, fin) • stops reading the file when it encounters either: • a new line character (copied into send_buffer) • EOF(End-Of-File) character • a NULL-termination character (‘\0’) is automatically appended • this is counted as one of the characters • strlen() – counts the number of characters excluding the NULL-character A 0 A 0 B 1 1 B strlen()=4 C 2 C 2 ‘\n’ 3 strlen()-1 3 ‘\0’ 4 4 ‘\0’ ‘\0’ send_buffer send_buffer
Data Format CLIENT Destination Port: 1235 checksum Length of segment DATA CRC_NUM PACKET 0 ABC ‘\r’ ‘\n’ User-defined Remove the line feed character from the row of data read from the file A 0 A 0 B 1 1 B strlen()=4 C 2 C 2 ‘\n’ 3 strlen()-1 3 ‘\0’ 4 4 ‘\0’ ‘\0’ send_buffer send_buffer
Start-up Codes (Client – Server) Rclient_UDP.cpp Rserver_UDP.cpp CLIENT SERVER File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... socket socket fopen(“file1_Windows.txt”, r) fopen(“file1_Saved”, w) Loop: recvfrom() send_unreliably(ACK) Loop: send_unreliably(data) recvfrom() send_unreliably(”CLOSE”) closesocket() Write everything into file1_Saved.txt fclose() closesocket()
Start-up Codes (Client – Server) 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... CLIENT SERVER fopen(“file1_Windows.txt”, r) fopen(“file1_Saved”, w) • Loop: • read one line from file • if(not EOF){ • create packet with header fields • store packet into send_buffer • send_unreliably(send_buffer) • Sleep(1); • recvfrom(receive_buffer) • trim ‘\r’, ‘\n’ from receive_buffer • } else { • fclose() • send_unreliably(”CLOSE”) • } Loop: recvfrom(receive_buffer) trim ‘\r’, ‘\n’ from receive_buffer process receive_buffer if(receive_buffercontains DATA){ create ACK packet send_unreliably(ACK) save_line_without_header } else { fclose() } closesocket() closesocket()
Start-up Codes Let’s have a look at the Start-up Codes (downloadable from our website)
Recommended Way of Testing the Codes (Client-Server) Parameters Settings
Parameters (Client – Server) Rclient_UDP.cpp Bits can be corrupted Rserver_UDP.cpp CLIENT SERVER Packets can be lost Sample run: Rclient 127.0.0.1 1235 0 0 Rserver1235 0 0
Ultimate Test Rclient_UDP.cpp Rserver_UDP.cpp CLIENT SERVER Bits can be corrupted Ultimate Test: Packets can be lost Rclient 127.0.0.1 1235 1 1 Rserver1235 1 1 You can simply inspect the contents of File1_Windows.txtand File1_Saved.txt, to check to see if they are exactly the same. File1_Windows.txt File1_Saved.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ...
Adding data transfer reliability Extending the codes
Go-Back N Let’s have a look at the Go-Back N Protocol Specifications… See Lecture-2012-7-Transport Layer-Part-1 (Slide #37)
Pipelining Protocol (Go Back-N) CLIENT (sender) Send a Window’s worth of packets CRC_NUM PACKET 0 ABC ‘\r’ ‘\n’ CRC_NUM PACKET 1 ABC ‘\r’ ‘\n’ CRC_NUM PACKET 2 ABC ‘\r’ ‘\n’ N=Window size = 4 base + (N-1) base Sequence Number Space
Pipelining Protocol (Go Back-N) CLIENT (sender) Send a Window’s worth of packets CRC_NUM PACKET 0 ABC ‘\r’ ‘\n’ CRC_NUM PACKET 1 ABC ‘\r’ ‘\n’ CRC_NUM PACKET 2 ABC ‘\r’ ‘\n’ ... N = Window size = 4 base + (N-1) base nextSequenceNum nextSequenceNum-1 Packets sent but not yet ACKed
Pipelining Protocol (Go Back-N) CLIENT (sender) Packets sent but not yet ACKed N = Window size = 4 base + (N-1) base nextSequenceNum nextSequenceNum-1 baseMax base We need to keep track of the ACK number received ACKnum
Pipelining Protocol (Go Back-N) CLIENT (sender) N = Window size = 4 0 1 2 3 time=0 Upon receipt of an ACK, slide the window forward base=0 baseMax=3 ACKnum=1 4 5 0 1 2 3 time=1 base=ACKnum+1 baseMax=base+(N-1)
Pipelining Protocol (Go Back-N) CLIENT (sender) N = Window size = 4 0 1 2 3 time=0 Transmit more packets (up to baseMax) base=0 baseMax=3 ACKnum=1 4 5 0 1 2 3 time=2 base=ACKnum+1 baseMax=base+(N-1)
Extending the codes WARNING: The following pseudo codes are not complete. They are meant just to give you an idea of how to implement a sliding Window protocol. The statements highlightedinredcorresponds to the suggested routines that need to be incorporated.
clock() void wait ( int seconds ) { clock_tendwait; endwait = clock () + seconds * CLOCKS_PER_SEC ; while (clock() < endwait) {} } Calculating the Elapsed Time clock_tstartTime, elapsedTime; startTime = clock(); … ... elapsedTime = (clock() - startTime) / CLOCKS_PER_SEC;
Extending the codes CLIENT SERVER 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... fopen(“file1_Saved”, w) fopen(“file1_Windows.txt”, r) Loop: recvfrom(receive_buffer) trim ‘\r’, ‘\n’ from receive_buffer extract CRC1 fromreceive_buffer extract data fromreceive_buffer calc CRC2 usingdata if(CRC1 == CRC2){ extract Packet Num if(PacketNum is in-order){ if(receive_buffercontains DATA){ create ACK packet send_unreliably(ACK) save_line_without_header update expectedSeqNum, base } else if(receive_buffercontains CLOSE) { fclose(); closesocket(); } } } • Loop: • read one line from file • if(not EOF){ • create packet with header fields • store packet into send_buffer • send_unreliably(send_buffer) • Sleep(1); • recvfrom(receive_buffer) • trim ‘\r’, ‘\n’ from receive_buffer • extract ACK number • update base, baseMax • } else { • fclose() • send_unreliably(”CLOSE”) • } closesocket()
Other Helpful Functions strchr • <cstring> • const char * strchr ( const char * str, int character ); char * strchr ( char * str, int character ); • Locate first occurrence of character in string • Returns a pointer to the first occurrence of character in the C string str.The terminating null-character is considered part of the C string. Therefore, it can also be located to retrieve a pointer to the end of a string.