程序代写代做代考 Reliable Data Transfer Protocol

Reliable Data Transfer Protocol

Reliable Data Transfer Protocol
IMPLEMENTATION TIPS

Recall
Reliable Data Transfer Mechanisms:

Checksum

Timer

Sequence number

ACK
NAK

Window, pipelining

socket
door

TCP
send buffer

TCP
receive buffer
socket
door

Packet ->

application
writes data
application
reads data

– 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

Transport Layer – TCP
‹#›
B

Client – Server
CLIENT
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_for_transmission.txt

SERVER
Empty
.
.
.
data_received.txt
Rclient_UDP.cpp
Rserver_UDP.cpp
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

See Lecture-6-Socket Programming-Part2
UDP Basics

Client – Server
CLIENT
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_for_transmission.txt

SERVER
Empty
.
.
.
data_received.txt
Rclient_UDP.cpp
Rserver_UDP.cpp
socket
socket
Rserver 1235 0 0
Rclient 127.0.0.1 1235 0 0
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.
Sample run:
Bits can get corrupted flag
Packets can get lost flag
Port: 1235

Client – Server
CLIENT
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_for_transmission.txt

SERVER
Empty
.
.
.
data_received.txt
Rclient_UDP.cpp
Rserver_UDP.cpp
socket
socket
Rserver 1235 0 0
Rclient 127.0.0.1 1235 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. data_for_transmission.txt, data_received.txt).

Client – Server
CLIENT
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_for_transmission.txt

SERVER
Empty
.
.
.
data_received.txt
Rclient_UDP.cpp
Rserver_UDP.cpp
socket
socket
Rserver 1235 0 0
Rclient 127.0.0.1 1235 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
CLIENT
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_for_transmission.txt

SERVER
Empty
.
.
.
data_received.txt
Rclient_UDP.cpp
Rserver_UDP.cpp
socket
socket
Rserver 1235 0 0
Rclient 127.0.0.1 1235 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
CLIENT
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_for_transmission.txt

SERVER
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_received.txt
Rclient_UDP.cpp
Rserver_UDP.cpp
socket
socket
Receives file contents
line-by-line, then stores everything
into a file
Reads file, then sends the contents
1 line at a time
UNRELIABLE CHANNEL
NETWORK LAYER
TRANSPORT LAYER
APPLICATION LAYER

Client – Server
CLIENT
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_for_transmission.txt

SERVER
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_received.txt
Rclient_UDP.cpp
Rserver_UDP.cpp
socket
socket
Receives file contents
line-by-line, then stores everything
into a file
Reads file, then sends the contents
1 line at a time
UNRELIABLE CHANNEL
NETWORK LAYER
TRANSPORT LAYER
APPLICATION LAYER
Simulated by a function named send_unreliably()

10

Unreliable Channel Simulation
int send_unreliably( int s, char * send_buffer,
struct sockaddr* remoteaddress) {

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 Optional in IPv4 int sendto( SOCKET s, char *buf, int msglen, int flags, struct sockaddr *to, int tolen ); Size of data may vary Header + data, in bytes Send data through a socket: sendto(SOCKET s, char *msg, int msglen, int flags, struct sockaddr *to, int tolen); sendto() Examples: bytes = sendto(s, send_buffer, strlen(send_buffer),0,(result->ai_addr),sizeof(struct sockaddr) ); //IPv4
int sin6len = sizeof(struct sockaddr_in6); //IPv6
bytes = sendto(s, send_buffer, strlen(send_buffer), 0, (struct sockaddr *)&clientAddress, sin6len);
s = socket (inside the socket descriptor: port and IP address…)
msg = a pointer to a buffer (array of characters)
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
PARAMETERS

The WSAStartup function is called to initiate use of WS2_32.dll.

Every Winsock application must load the appropriate version of the Winsock DLL. If you fail to load the Winsock library before calling a Winsock function, the function will return a SOCKET_ERROR and the error will be WSANOTINITIALISED .

Loading the Winsock library is accomplished by calling the WSAStartup function

WSVERS
The high order byte specifies the minor version (revision) number; the low-order byte specifies the major version number.

Receive data
int recvfrom(SOCKET s, char *msg, int msglen,
int flags, struct sockaddr *from, int *fromlen)
recvfrom()
Example:

recvfrom(s, rbuffer, 1, 0,(struct sockaddr*) &from, &len); //IPv4
int sin6len = sizeof(struct sockaddr_in6); //IPv6
bytes = recvfrom(s, receive_buffer, sizeof(receive_buffer), 0,
(struct sockaddr*)&serverAddress,&sin6len ); //IPv6
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
PARAMETERS

‹#›
The WSAStartup function is called to initiate use of WS2_32.dll.

Every Winsock application must load the appropriate version of the Winsock DLL. If you fail to load the Winsock library before calling a Winsock function, the function will return a SOCKET_ERROR and the error will be WSANOTINITIALISED .

Loading the Winsock library is accomplished by calling the WSAStartup function

WSVERS
The high order byte specifies the minor version (revision) number; the low-order byte specifies the major version number.

Client – Server
CLIENT
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_for_transmission.txt

SERVER
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_received.txt
Rclient_UDP.cpp
Rserver_UDP.cpp
socket
socket
Receives file contents
line-by-line, then stores into a file
Destination Port: 1235
DATA
checksum
Length of segment
Reads file, then sends the contents
1 line at a time
UDP SEGMENT

Client – Server
CLIENT
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_for_transmission.txt

SERVER
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

data_received.txt
Rclient_UDP.cpp
Rserver_UDP.cpp
socket
socket
Receives file contents
line-by-line, then stores into a file
Destination Port: 1235
DATA
0 ABCDEF
checksum
Length of segment
Reads file, then sends the contents
1 line at a time
PACKET 0
‘\r’
‘\n’
CRC_NUM

User-defined

Start-up Codes
(Client-Server)

Let’s have a look at the CRC function provided as part of the start-up codes and the CRC test program.
CRC

//*******************************************************************
// CREATE CLIENT’S SOCKET
//*******************************************************************
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) { printf("socket failed\n"); WSACleanup(); exit(1); } //nonblocking option u_long iMode=1; ioctlsocket(s, FIONBIO, &iMode); Socket (in non-blocking mode) 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. Done in the client-side only. Set the socket I/O mode: In this case FIONBIO enables or disables the blocking mode for the socket based on the numerical value of iMode. If iMode = 0, blocking is enabled; If iMode != 0, non-blocking mode is enabled. Start-up Codes (Client – Server) CLIENT 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... data_for_transmission.txt SERVER 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... data_received.txt Rclient_UDP.cpp Rserver_UDP.cpp socket socket Receives file contents line-by-line, then stores into a file Reads file using fgets(), then sends the contents 1 line at a time Loop: send_unreliably(data) Sleep(1) recvfrom() Loop: recvfrom() send_unreliably(ACK) fopen(“data_for_transmission.txt”, rb) fopen(“data_received.txt”, w) Non-blocking mode Start-up Codes (Client – Server) CLIENT 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... data_for_transmission.txt SERVER 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... data_received.txt Rclient_UDP.cpp Rserver_UDP.cpp socket socket Loop: send_unreliably(data) recvfrom() Loop: recvfrom() send_unreliably(ACK) fopen(“data_for_transmission.txt”, rb) fopen(“data_received.txt”, w) Some notes on fopen() : In text mode, carriage return–linefeed combinations are translated into single linefeeds on input (reading a file), and linefeed characters are translated to carriage return–linefeed combinations on output (writing a file). The function void save_line_without_header(char * receive_buffer,FILE *fout) takes advantage of this knowledge. Reading the file contents The client reads the file contents line by line using fgets() fgets(send_buffer, SEGMENT_SIZE, fin) stops reading the file when SEGMENT_SIZE-1 characters have been read, or either it encounters a newline or EOF, whichever happens first : a new line character (‘\n’)(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 CLIENT A B C ‘\n’ ‘\0’ send_buffer strlen()=4 ‘\0’ ‘\0’ send_buffer strlen()-1 0 1 2 3 4 0 1 2 3 4 A B C Data Format CLIENT A B C ‘\n’ ‘\0’ send_buffer strlen()=4 ‘\0’ ‘\0’ send_buffer strlen()-1 0 1 2 3 4 0 1 2 3 4 A B C Destination Port: 1235 DATA ABC checksum Length of segment PACKET 0 ‘\r’ ‘\n’ CRC_NUM User-defined Remove the line feed character from the row of data read from the file UDP datagram CLIENT 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... data_for_transmission.txt SERVER 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... data_received.txt Rclient_UDP.cpp Rserver_UDP.cpp socket socket Loop: send_unreliably(data) recvfrom() Loop: recvfrom() send_unreliably(ACK) fopen(“data_for_transmission.txt”, rb) fopen(“data_received.txt”, w) send_unreliably(”CLOSE”) closesocket() Write everything into data_received.txt fclose() closesocket() Start-up Codes (Client – Server) Non-blocking mode Let’s see more details... Start-up Codes (Client – Server) CLIENT SERVER 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_buffer contains DATA){ create ACK packet send_unreliably(ACK) save_line_without_header() } else { fclose() } fopen(“data_for_transmission.txt”, rb) fopen(“data_received.txt”, w) closesocket() closesocket() 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... Should be modified according to the length of your packet header Let’s have a look at the Start-up Codes (downloadable from Stream) Start-up Codes Recommended Way of Testing the Codes (Client-Server) Parameters Settings Parameters (Client – Server) CLIENT SERVER Rclient_UDP.cpp Rserver_UDP.cpp Rserver 1235 0 0 Rclient 127.0.0.1 1235 0 0 Sample run: Bits can be corrupted Packets can be lost CLIENT SERVER COMMENTS 00 00 Packets can never be corrupted nor lost 01 00 Client may lose packets 00 01 Server may lose ACK packets 01 01 Both client and server may lose packets 10 00 Client may send packets with corrupted bits 00 10 Server may send ACKs with corrupted bits 10 10 Packets from both client and server may have corrupted bits 11 11 Packets from both client and server may have corrupted bits; packets may be lost as well Ultimate Test CLIENT SERVER Rclient_UDP.cpp Rserver_UDP.cpp Rserver 1235 1 1 Rclient 127.0.0.1 1235 1 1 Ultimate Test: Bits can be corrupted Packets can be lost You can simply inspect the contents of data_for_transmission.txt and data_received.txt, to check to see if they are exactly the same. 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... data_for_transmission.txt 0 ABCDEF 1 ABCDEF 2 ABCDEF 3 ABCDEF ... data_received.txt Testing using a batch file Run.bat START cmd /k "RServer_UDP_ipv6\Rserver_UDP 1235 1 0" START cmd /k "RClient_UDP_ipv6\Rclient_UDP localhost 1235 1 0" Adding data transfer reliability Extending the codes Let’s have a look at the Go-Back N Protocol Specifications… See Lecture-7-Transport Layer-Part-1 (Slide #37) Go-Back N Pipelining Protocol (Go Back-N) CLIENT (sender) base base + (N-1) ABC PACKET 0 ‘\r’ ‘\n’ CRC_NUM ABC PACKET 1 ‘\r’ ‘\n’ CRC_NUM ABC PACKET 2 ‘\r’ ‘\n’ CRC_NUM Send a Window’s worth of packets N=Window size = 4 Sequence Number Space Pipelining Protocol (Go Back-N) base base + (N-1) ABC PACKET 0 ‘\r’ ‘\n’ CRC_NUM ABC PACKET 1 ‘\r’ ‘\n’ CRC_NUM ABC PACKET 2 ‘\r’ ‘\n’ CRC_NUM Send a Window’s worth of packets N = Window size = 4 nextSequenceNum-1 Packets sent but not yet ACKed ... nextSequenceNum CLIENT (sender) Pipelining Protocol (Go Back-N) base base + (N-1) N = Window size = 4 nextSequenceNum-1 Packets sent but not yet ACKed nextSequenceNum base baseMax ACKnum We need to keep track of the ACK number received CLIENT (sender) Pipelining Protocol (Go Back-N) N = Window size = 4 Upon receipt of an ACK, slide the window forward base=0 baseMax=3 ACKnum=1 base=ACKnum+1 baseMax=base+(N-1) 0 1 2 3 0 1 2 3 4 5 time=0 time=1 CLIENT (sender) Pipelining Protocol (Go Back-N) N = Window size = 4 Transmit more packets (up to baseMax) base=0 baseMax=3 ACKnum=1 base=ACKnum+1 baseMax=base+(N-1) 0 1 2 3 0 1 2 3 4 5 time=0 time=2 CLIENT (sender) 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 highlighted in red corresponds to the suggested routines that need to be incorporated. 40 Calculating the Elapsed Time clock() void wait ( int seconds ) { clock_t endwait; endwait = clock () + seconds * CLOCKS_PER_SEC ; while (clock() < endwait) {} } clock_t startTime, elapsedTime; startTime = clock(); … ... elapsedTime = (clock() - startTime) / CLOCKS_PER_SEC;

40

Extending the codes
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”)
}

Loop:
recvfrom(receive_buffer)
trim ‘\r’, ‘\n’ from receive_buffer
extract CRC1 from receive_buffer
extract data from receive_buffer
calc CRC2 using data
if(CRC1 == CRC2){
extract Packet Num
if(PacketNum is in-order){
if(receive_buffer contains DATA){
create ACK packet
send_unreliably(ACK)
save_line_without_header
update expectedSeqNum, base
}
else if(receive_buffer contains CLOSE) {
fclose(); closesocket();
}
}
}
fopen(“data_for_transmission.txt”, r)
fopen(“file1_Saved”, w)
closesocket()
0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

0 ABCDEF
1 ABCDEF
2 ABCDEF
3 ABCDEF

SERVER
CLIENT

Other Helpful Functions
See tokenizer2.cpp

strtok()

Other Helpful Functions
strchr

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.

/docProps/thumbnail.jpeg