Skip to content

Commit 7d79500

Browse files
committed
⏳ RTT ✅ ACK
Signed-off-by: Azmah-Bad <[email protected]>
1 parent f8da283 commit 7d79500

File tree

8 files changed

+199
-53
lines changed

8 files changed

+199
-53
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ out/*
44
.vscode
55
server.dSYM
66
.DS_Store
7-
!.gitkeep
7+
!.gitkeep
8+
venv
9+
src/client/rcv_mock.pdf

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ implmentation of TCP over a UDP socket in C
77

88
## Features
99

10-
- [ ] Server - Client over UDP
11-
- [ ] 3 way handshake
12-
- [ ] accept()
13-
- [ ] segmentation
10+
- [X] Server - Client over UDP
11+
- [X] 3 way handshake
12+
- [X] accept()
13+
- [X] segmentation
1414
- [ ] ACK
1515
- [ ] slow start
1616
- [ ] Congestion Avoidance

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
func-timeout==4.3.5

src/client/client.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <string.h>
22

33
int UDPConnect(int clientSocket, struct sockaddr_in *clientAddress, int clientLengthUDP);
4-
int isReceive(char *expected, int mSocketUDP, struct sockaddr_in *clientAddress, int clientLengthUDP);
4+
int isReceive(char *expected, int mSocketUDP, struct sockaddr_in *clientAddress, int clientLengthUDP);
5+
int recvFile(int clientSocket, struct sockaddr_in *clientAddress, int clientLengthUDP);

src/client/client.py

+46-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,49 @@ def changePort(ClientSocket):
4848
dataPort = int(message)
4949
return dataPort
5050

51+
def rcvfile(ClientSocket):
52+
rawData , _ = rcv(ClientSocket, 256)
53+
data = rawData.decode().split("-")
54+
fileSize = int(data[1])
55+
fileName = data[0]
56+
segments = {}
57+
log("RCV_FILE", f"recieving file {fileName} {fileSize // 1000} kB")
58+
ACKedsegment=0
59+
NACKed = []
60+
for _ in range((fileSize // 1000) + 1) :
61+
# we receive and write in the file
62+
rawData,_ = rcv(ClientSocket, 1024)
63+
# print("RAWDATA :: ",rawData)
64+
segmentID = int(rawData[:20])
65+
data = rawData[20:]
66+
segments[segmentID] = data
67+
68+
#SEND ACK
69+
if segmentID == ACKedsegment + 1:
70+
ACKedsegment+=1
71+
else :
72+
NACKed.append(segmentID)
73+
for _ in NACKed:
74+
if ACKedsegment + 1 in NACKed:
75+
ACKedsegment += 1
76+
NACKed.pop(NACKed.index(ACKedsegment))
77+
send(ClientSocket, PORT, f"ACK:{ACKedsegment}")
78+
log("RCV_FILE", f"ACK: ACKng {ACKedsegment}")
79+
80+
81+
# log("RCV_FILE", f"segment {segmentID} recieved")
82+
log("RCV_FILE", "file recieved with success")
83+
84+
file = b""
85+
for index in range(0, (fileSize // 1000) + 1):
86+
file += segments[index]
87+
log("RCV_FILE", "file rearranged with success")
88+
89+
with open('rcv_' + fileName,'wb') as f: # Open in binary
90+
f.write(file)
91+
log("RCV_FILE", "file written with success")
92+
93+
5194

5295
def client():
5396
ClientSocket = initSocket()
@@ -56,7 +99,9 @@ def client():
5699

57100
dataPort = changePort(ClientSocket)
58101
log("CHANGE_PORT", f"data port on {dataPort}")
59-
102+
103+
rcvfile(ClientSocket)
104+
60105

61106
if __name__ == "__main__":
62107
client()

src/client/clientUDP.c

+72-34
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
#include "../common/common.h"
22
#include "client.h"
33

4-
5-
64
int main(int argc, char const *argv[])
7-
{
8-
if (argc != 3){
5+
{
6+
if (argc != 3)
7+
{
98
printf("Error syntax : ./clientUCP <ip_server> <port_server>\n");
109
return 1;
1110
}
1211

1312
// get IP andd port from cmd line aregument
14-
const char * IP_SERVER = argv[1];
13+
const char *IP_SERVER = argv[1];
1514
int PORT = atoi(argv[2]);
1615
char userInput[100];
1716

18-
1917
// init the addresses
2018
struct sockaddr_in serverAddress;
2119

2220
// create socket
23-
int clientSocket = (int) malloc(sizeof(int));
21+
int clientSocket = (int)malloc(sizeof(int));
2422
clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
2523

2624
if (clientSocket == -1)
@@ -37,71 +35,53 @@ int main(int argc, char const *argv[])
3735

3836
// assign IP, PORT
3937
serverAddress.sin_port = htons(PORT);
40-
inet_aton(IP_SERVER,(struct in_addr *) serverAddress.sin_addr.s_addr);
38+
inet_aton(IP_SERVER, (struct in_addr *)serverAddress.sin_addr.s_addr);
4139
serverAddress.sin_family = AF_INET;
4240

4341
socklen_t addressLength = sizeof(serverAddress);
4442

4543
// connect
46-
if (UDPConnect(clientSocket, &serverAddress,addressLength))
44+
if (UDPConnect(clientSocket, &serverAddress, addressLength))
4745
{
4846
info("HANDSHAKE", "handshake completed 🤝"); //receiveSYN
4947
}
5048
else
5149
{
52-
info("HANDSHAKE","failed to connect to server");
50+
info("HANDSHAKE", "failed to connect to server");
5351
}
5452

55-
56-
// get user input
57-
printf("enter data to be sent over\n");
58-
gets(userInput);
59-
60-
//write data into the socket
61-
int writeValue = write(clientSocket, userInput, sizeof(userInput));
62-
if (writeValue < 0)
63-
{
64-
printf("writing failed...\nwrite value: %d\n", writeValue);
65-
return 1;
66-
}
67-
else
68-
{
69-
printf("data written with success 🎉...\n");
70-
71-
}
53+
recvFile(clientSocket, &serverAddress, addressLength);
7254

7355
close(clientSocket);
7456

7557
return 0;
7658
}
7759

78-
79-
int UDPConnect(int clientSocket, struct sockaddr_in * clientAddress, int clientLengthUDP){
60+
int UDPConnect(int clientSocket, struct sockaddr_in *clientAddress, int clientLengthUDP)
61+
{
8062

8163
//send SYN
82-
if (sendto(clientSocket, SYN, sizeof(SYN),0,(const struct sockaddr *) clientAddress, clientLengthUDP) > 0)
64+
if (sendto(clientSocket, SYN, sizeof(SYN), 0, (const struct sockaddr *)clientAddress, clientLengthUDP) > 0)
8365
{
8466
printf("[CONNECT] SYN sent 🎉...\n");
85-
8667
}
8768
else
8869
{
8970
perror("SYN couldn't be sent...\n");
9071
return 0;
9172
}
9273
//receive SYNACK
93-
if (isReceive(SYNACK,clientSocket, clientAddress,clientLengthUDP))
74+
if (isReceive(SYNACK, clientSocket, clientAddress, clientLengthUDP))
9475
{
9576
printf("[CONNECT] SYNACK received properly 🎉🎉...\n");
96-
9777
}
9878
else
9979
{
10080
perror("SYNACK reception failed...\n");
10181
return 0;
10282
}
10383
//send ACK
104-
if (sendto(clientSocket, ACK, sizeof(ACK), 0, (const struct sockaddr *) clientAddress, clientLengthUDP) > 0)
84+
if (sendto(clientSocket, ACK, sizeof(ACK), 0, (const struct sockaddr *)clientAddress, clientLengthUDP) > 0)
10585
{
10686
printf("[CONNECT] ACK sent 🎉🎉🎉...\n");
10787
}
@@ -114,3 +94,61 @@ int UDPConnect(int clientSocket, struct sockaddr_in * clientAddress, int clientL
11494
return 1;
11595
}
11696

97+
int recvFile(int clientSocket, struct sockaddr_in *clientAddress, int clientLengthUDP)
98+
{
99+
// rcv header
100+
char header[18];
101+
if (recvfrom(clientSocket, header, sizeof(header), 0, (struct sockaddr *)clientAddress, (socklen_t *)&clientLengthUDP) > 0)
102+
{
103+
info("RCVFILE", "Received header 🎉...");
104+
char fileSizeChar[6];
105+
int i = 9;
106+
while(header[i] != NULL){
107+
fileSizeChar[i - 9] = header[i];
108+
i++;
109+
}
110+
int fileSize = atoi(fileSizeChar);
111+
char fileBuffer[fileSize];
112+
int numberSegments= fileSize / 1020;
113+
114+
bzero(fileBuffer, sizeof(fileBuffer));
115+
116+
for (int segmentID = 0; segmentID < numberSegments; segmentID++){
117+
char segmentBuffer[1020];
118+
if (recvfrom(clientSocket, segmentBuffer, sizeof(segmentBuffer), 0, (struct sockaddr *)clientAddress, (socklen_t *)&clientLengthUDP) > 0)
119+
{
120+
char segmentIDrcvChar[3];
121+
int segmentIDrcv = 0;
122+
for (int i = 0; i < 3; i++)
123+
{
124+
segmentIDrcvChar[i] = segmentBuffer[i];
125+
printf("%d", i);
126+
}
127+
segmentIDrcv = (int) atoi(segmentIDrcvChar[2]);
128+
printf("[RCVFILE] received segment %d\n", segmentIDrcv);
129+
char ack[6];
130+
bzero(ack, sizeof(ack));
131+
132+
sprintf(ack, "ACK%d", segmentIDrcv);
133+
if(sendto(clientSocket, ack, sizeof(ack), 0, clientAddress, clientLengthUDP) > 0)
134+
{
135+
info("ACK","Ack sent...");
136+
}
137+
else
138+
{
139+
info("ACK","ACK couldn't be sent...");
140+
exit (1);
141+
}
142+
143+
}
144+
}
145+
146+
info("RCVFILE", "Reciving segmented files ...");
147+
}
148+
else
149+
{
150+
info("RCVFILE", "Header reception failed...");
151+
exit(1);
152+
}
153+
return 1;
154+
}

src/server/server.c

+16-12
Original file line numberDiff line numberDiff line change
@@ -142,26 +142,30 @@ int sendFile(int mSocketUDP, struct sockaddr_in *clientAddress, int clientLength
142142

143143
// segment
144144
long nbOfSegment = size / 1020;
145+
char header[18];
146+
sprintf(header, "SEND:PDF:%d", size);
147+
sendto(mSocketUDP, header, sizeof(header), 0, clientAddress, clientLengthUDP);
148+
145149
for (int i = 0; i < nbOfSegment; i++)
146150
{
147151
buffer[0] = (char)i / 100;
148152
buffer[1] = (char)(i / 100) % 10;
149153
buffer[2] = (char)i % 10;
150-
// buffer[3]="-";
154+
151155
for (int j = 0; j < 1020; j++)
152156
{
153157
buffer[j + 3] = fileBuffer[i * 1020 + j];
154-
info("SENDFILE", "file segmented...");
155-
156-
if (sendto(mSocketUDP, buffer, sizeof(buffer), 0, clientAddress, clientLengthUDP) > 0)
157-
{
158-
info("SENDFILE", "segment sent 🎉...");
159-
}
160-
else
161-
{
162-
perror("[CONNECT] SYNACK couldn't be sent...\n");
163-
return 0;
164-
}
158+
}
159+
info("SENDFILE", "file segmented...");
160+
161+
if (sendto(mSocketUDP, buffer, sizeof(buffer), 0, clientAddress, clientLengthUDP) > 0)
162+
{
163+
info("SENDFILE", "segment sent 🎉...");
164+
}
165+
else
166+
{
167+
perror("[CONNECT] SYNACK couldn't be sent...\n");
168+
return 0;
165169
}
166170
}
167171
}

0 commit comments

Comments
 (0)