Вы находитесь на странице: 1из 40

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 - Verification of integrity of packet

 Timer - Signals necessary re-transmission is required

 Sequence number
- Keeps track of which packet has been sent and received

 ACK
- Indicates receipt of packet in good or bad form
 NAK

 Window, pipelining
2
- Allows for the sending of multiple yet-to-be-acknowledged packets
Transport Layer – TCP
B
Client - Server
Rclient_UDP.cpp Rserver_UDP.cpp

CLIENT SERVER
File1_Windows.txt File1_Saved.txt
0 ABCDEF Empty
1 ABCDEF .
2 ABCDEF .
3 ABCDEF .
...
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 Empty
1 ABCDEF .
2 ABCDEF .
3 ABCDEF .
...
socket socket

Port: 1235
Sample run:

Rclient 127.0.0.1 1235 0 0 Rserver 1235 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 Empty
1 ABCDEF .
2 ABCDEF .
3 ABCDEF .
...
socket socket

Rclient 127.0.0.1 1235 0 0 Rserver 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. File1_Windows.txt, File1_Saved.txt).
Client - Server
Rclient_UDP.cpp Rserver_UDP.cpp

CLIENT SERVER
File1_Windows.txt File1_Saved.txt
0 ABCDEF Empty
1 ABCDEF .
2 ABCDEF .
3 ABCDEF .
...
socket socket

Rclient 127.0.0.1 1235 0 0 Rserver 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
Rclient_UDP.cpp Rserver_UDP.cpp

CLIENT SERVER
File1_Windows.txt File1_Saved.txt
0 ABCDEF Empty
1 ABCDEF .
2 ABCDEF .
3 ABCDEF .
...
socket socket

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

Reads file, then sends the contents Receives file contents


1 line at a time 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 0 ABCDEF
1 ABCDEF 1 ABCDEF
2 ABCDEF 2 ABCDEF
3 ABCDEF 3 ABCDEF
... ...
socket socket

Reads file, then sends the contents Receives file contents


1 line at a time line-by-line, then stores everything
into a file
TRANSPORT LAYER

Simulated by a UNRELIABLE CHANNEL


function named
send_unreliably() NETWORK LAYER
Unreliable Channel Simulation
int send_unreliably( int s, char * send_buffer,
struct sockaddr_in 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);
… You are not allowed to modify
} else if(fate==2){ // lose the packet this function in the
printf("X-- LOST %s \n",send_buffer); assignment.
}
}
UDP segment structure

Optional in IPv4

• The optional parameters are not even included in


the sendto() function. int sendto(
SOCKET s,
• The O/S will automatically char *buf,
provide the IP address of int msglen,
the sender of the int flags,
segment. struct sockaddr *to,
int tolen
);
sendto()
•Send data through a socket:
sendto(SOCKET s, char *msg, int msglen, int flags,
struct sockaddr *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,(struct sockaddr*) to, &len);
recvfrom()
 Receive data
int recvfrom(SOCKET s, char *msg, int msglen,
int flags, struct sockaddr *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,(struct sockaddr *) &from, &len); 14
Client - Server
Rclient_UDP.cpp Rserver_UDP.cpp

CLIENT SERVER
File1_Windows.txt File1_Saved.txt
0 ABCDEF 0 ABCDEF
1 ABCDEF 1 ABCDEF
2 ABCDEF 2 ABCDEF
3 ABCDEF 3 ABCDEF
... ...
socket socket

Reads file, then sends the contents Receives file contents


1 line at a time 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 0 ABCDEF
1 ABCDEF 1 ABCDEF
2 ABCDEF 2 ABCDEF
3 ABCDEF 3 ABCDEF
... ...
socket socket

Reads file, then sends the contents Receives file contents


1 line at a time 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
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_long iMode=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 0 ABCDEF
1 ABCDEF 1 ABCDEF
2 ABCDEF 2 ABCDEF
3 ABCDEF 3 ABCDEF
... ...
socket socket

Reads file using fgets(), then sends the Receives file contents
contents 1 line at a time line-by-line, then stores into a file
fopen(“file1_Windows.txt”, r) fopen(“file1_Saved”, w)
Loop: Loop:
send_unreliably(data) recvfrom()
recvfrom() send_unreliably(ACK)
Reading the file contents
The client reads the file contents line by line using fgets() CLIENT
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 B 1
strlen()=4
C 2 C 2
‘\n’ 3 strlen()-1 ‘\0’ 3
‘\0’ 4 ‘\0’ 4

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 B 1
strlen()=4
C 2 C 2
‘\n’ 3 strlen()-1 ‘\0’ 3
‘\0’ 4 ‘\0’ 4

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 0 ABCDEF
1 ABCDEF 1 ABCDEF
2 ABCDEF 2 ABCDEF
3 ABCDEF 3 ABCDEF
... ...
socket socket

fopen(“file1_Windows.txt”, r) fopen(“file1_Saved”, w)
Loop: Loop:
send_unreliably(data) recvfrom()
recvfrom() send_unreliably(ACK)

send_unreliably(”CLOSE”)
closesocket() Write everything into file1_Saved.txt
fclose()
closesocket()
Start-up Codes (Client – Server)
0 ABCDEF
0 ABCDEF
CLIENT 1 ABCDEF
2 ABCDEF
SERVER 1 ABCDEF
2 ABCDEF
3 ABCDEF
3 ABCDEF
...
...
fopen(“file1_Windows.txt”, r) fopen(“file1_Saved”, w)
Loop: Loop:
read one line from file recvfrom(receive_buffer)
if(not EOF){ trim ‘\r’, ‘\n’ from receive_buffer
create packet with header fields process receive_buffer
store packet into send_buffer if(receive_buffer contains DATA){
send_unreliably(send_buffer) create ACK packet
Sleep(1); send_unreliably(ACK)
recvfrom(receive_buffer) save_line_without_header
trim ‘\r’, ‘\n’ from receive_buffer } else {
} else { fclose()
fclose() }
send_unreliably(”CLOSE”)
}
closesocket()
closesocket()
Start-up Codes

Let’s have a look at the Start-up Codes


(downloadable from our website)
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 Rserver 1235 0 0
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 have corrupt bits
00 10 Server may have corrupt bits
10 10 Both client and server may have corrupted bits
11 11 Both client and server may have corrupted bits and may
lose packets
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 Rserver 1235 1 1

You can simply inspect the contents of File1_Windows.txt and


File1_Saved.txt, to check to see if they are exactly the same.

File1_Windows.txt File1_Saved.txt
0 ABCDEF 0 ABCDEF
1 ABCDEF 1 ABCDEF
2 ABCDEF 2 ABCDEF
3 ABCDEF 3 ABCDEF
... ...
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 Send a Window’s worth of packets
(sender)
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 base + (N-1)

Sequence Number Space


Pipelining Protocol (Go Back-N)
CLIENT Send a Window’s worth of packets
(sender)
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 base + (N-1)

nextSequenceNum

Packets sent but nextSequenceNum-1


not yet ACKed
Pipelining Protocol (Go Back-N)
CLIENT Packets sent but
(sender) not yet ACKed

N = Window size = 4

base base + (N-1)


nextSequenceNum
nextSequenceNum-1

base baseMax 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


base=0 ACK, slide the
baseMax=3 window forward

ACKnum=1

0 1 2 3 4 5
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
base=0 (up to baseMax)
baseMax=3

ACKnum=1

0 1 2 3 4 5
time=2

base=ACKnum+1
baseMax=base+(N-1)
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.
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;

38
Extending the codes
CLIENT 0 ABCDEF SERVER 0 ABCDEF
1 ABCDEF 1 ABCDEF
fopen(“file1_Windows.txt”, r) 2 ABCDEF fopen(“file1_Saved”, w) 2 ABCDEF
3 ABCDEF 3 ABCDEF
Loop: ... Loop: ...

read one line from file recvfrom(receive_buffer)


if(not EOF){ trim ‘\r’, ‘\n’ from receive_buffer
create packet with header fields extract CRC1 from receive_buffer
store packet into send_buffer extract data from receive_buffer
send_unreliably(send_buffer) calc CRC2 using data
Sleep(1); if(CRC1 == CRC2){
recvfrom(receive_buffer) extract Packet Num
trim ‘\r’, ‘\n’ from receive_buffer if(PacketNum is in-order){
extract ACK number if(receive_buffer contains DATA){
update base, baseMax create ACK packet
} else { send_unreliably(ACK)
fclose() save_line_without_header
send_unreliably(”CLOSE”) update expectedSeqNum, base
} }
else if(receive_buffer contains CLOSE) {
closesocket() fclose(); 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.

Вам также может понравиться