diff --git a/Reti/Laboratorio/Assigment4/EchoServer2/client b/Reti/Laboratorio/Assigment4/EchoServer2/client
new file mode 100755
index 0000000000000000000000000000000000000000..4ef6f9f2c3fa9db243efc58a0a4a42242280e5bf
Binary files /dev/null and b/Reti/Laboratorio/Assigment4/EchoServer2/client differ
diff --git a/Reti/Laboratorio/Assigment4/EchoServer2/client.c b/Reti/Laboratorio/Assigment4/EchoServer2/client.c
index 98b16552807d37ec282c36892fb4cb5c5a39a200..6dc11ad7daac86eb6685a81bd5db6f2a71124a46 100644
--- a/Reti/Laboratorio/Assigment4/EchoServer2/client.c
+++ b/Reti/Laboratorio/Assigment4/EchoServer2/client.c
@@ -13,10 +13,8 @@ int main(int argc, char *argv[])
     char valueToReceive[256] = {'\0'};
     char iterationsServer[256] = {'\0'};
 
-    int iterations;
     printf("Inserire il numero di iterazioni: ");
-    scanf("%d", &iterations);
-    snprintf(iterationsServer, sizeof(iterationsServer), "%d", iterations);
+    scanf("%s", iterationsServer);
 
     int simpleSocket = 0;
     int simplePort = 0;
@@ -71,22 +69,17 @@ int main(int argc, char *argv[])
     }
 
     // Inviando il numero di iterazioni al server
-    write(simpleSocket, iterationsServer, strlen(valueToSend));
+    write(simpleSocket, iterationsServer, strlen(iterationsServer));
 
+    int iterations = atoi(iterationsServer);
     for (int i = 0; i < iterations; ++i)
     {
-
-        /* get the message from the server   */
-        // returnStatus = read(simpleSocket, buffer, sizeof(buffer));
-
         printf("Inserire il valore da voler inviare al server: ");
         scanf("%s", valueToSend);
         write(simpleSocket, valueToSend, strlen(valueToSend));
         read(simpleSocket, valueToReceive, sizeof(valueToReceive));
         printf("\n\nEcho: %s\n", valueToReceive);
-        close(simpleSocket);
     }
-
     close(simpleSocket);
     return 0;
 }
diff --git a/Reti/Laboratorio/Assigment4/EchoServer2/server b/Reti/Laboratorio/Assigment4/EchoServer2/server
new file mode 100755
index 0000000000000000000000000000000000000000..fbdcc586ba39dad4c81beaa803884620db73656a
Binary files /dev/null and b/Reti/Laboratorio/Assigment4/EchoServer2/server differ
diff --git a/Reti/Laboratorio/Assigment4/EchoServer2/server.c b/Reti/Laboratorio/Assigment4/EchoServer2/server.c
index 1da16588c0a1407918296f311109dd2cf82506c8..15374b002837cedc8a2b09640e3276e128a26505 100644
--- a/Reti/Laboratorio/Assigment4/EchoServer2/server.c
+++ b/Reti/Laboratorio/Assigment4/EchoServer2/server.c
@@ -88,32 +88,35 @@ int main(int argc, char *argv[])
     int clientNameLength = sizeof(clientName);
 
     /* wait here */
+    while(1){
+        simpleChildSocket =
+            accept(simpleSocket, (struct sockaddr *)&clientName, &clientNameLength);
 
-    simpleChildSocket =
-        accept(simpleSocket, (struct sockaddr *)&clientName, &clientNameLength);
-
-    if (simpleChildSocket == -1)
-    {
-        fprintf(stderr, "Cannot accept connections!\n");
-        close(simpleSocket);
-        exit(1);
-    }
-
-    char bufferRead[256] = {'\0'};
-    read(simpleChildSocket, bufferRead, sizeof(bufferRead));
+        if (simpleChildSocket == -1)
+        {
+            fprintf(stderr, "Cannot accept connections!\n");
+            close(simpleSocket);
+            exit(1);
+        }
 
-    while (1)
-    {
-        // Read message from client
+        char bufferRead[256] = {'\0'};
         read(simpleChildSocket, bufferRead, sizeof(bufferRead));
         printf("Received: %s\n", bufferRead);
-        char valueToSend[256] = {'\0'};
-        snprintf(valueToSend, sizeof(valueToSend), "%s", bufferRead);
-        write(simpleChildSocket, valueToSend, sizeof(valueToSend));
+        int iterations = atoi(bufferRead);
 
-        close(simpleChildSocket);
-    }
 
+        for (int i = 0; i < iterations; ++i)
+        {
+            char bufferRead[256] = {'\0'};
+            // Read message from client
+            read(simpleChildSocket, bufferRead, sizeof(bufferRead));
+            printf("Received: %s\n", bufferRead);
+            char valueToSend[256] = {'\0'};
+            snprintf(valueToSend, sizeof(valueToSend), "%s", bufferRead);
+            write(simpleChildSocket, valueToSend, sizeof(valueToSend));
+        }
+        close(simpleChildSocket);
+        }
     close(simpleSocket);
     return 0;
 }
diff --git a/Reti/Laboratorio/Assigment4/EchoServer3/client b/Reti/Laboratorio/Assigment4/EchoServer3/client
new file mode 100755
index 0000000000000000000000000000000000000000..00c3da4cc31d46c2b704caf8973f7f2349388806
Binary files /dev/null and b/Reti/Laboratorio/Assigment4/EchoServer3/client differ
diff --git a/Reti/Laboratorio/Assigment4/EchoServer3/client.c b/Reti/Laboratorio/Assigment4/EchoServer3/client.c
new file mode 100644
index 0000000000000000000000000000000000000000..62c57068e597f4e4e3b0f0c2388f8af043b46bae
--- /dev/null
+++ b/Reti/Laboratorio/Assigment4/EchoServer3/client.c
@@ -0,0 +1,97 @@
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+void clean_buffer(void* buffer, size_t buffer_size){ 
+    char* bufferChar = (char *) buffer;
+    for(size_t i = 0; i < buffer_size; ++i){
+        bufferChar[i] = '\0';
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    char valueToSend[256] = {'\0'};
+    char valueToReceive[256] = {'\0'};
+    char iterationsServer[256] = {'\0'};
+
+    printf("Inserire il numero di iterazioni: ");
+    scanf("%s", iterationsServer);
+
+    int simpleSocket = 0;
+    int simplePort = 0;
+    int returnStatus = 0;
+    char buffer[256] = "";
+    struct sockaddr_in simpleServer;
+
+    if (argc != 3)
+    {
+        fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]);
+        exit(1);
+    }
+
+    /* create a streaming socket      */
+    simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+    if (simpleSocket == -1)
+    {
+        fprintf(stderr, "Could not create a socket!\n");
+        exit(1);
+    }
+    else
+    {
+        fprintf(stderr, "Socket created!\n");
+    }
+
+    /* retrieve the port number for connecting */
+    simplePort = atoi(argv[2]);
+
+    /* setup the address structure */
+    /* use the IP address sent as an argument for the server address  */
+    // bzero(&simpleServer, sizeof(simpleServer));
+    memset(&simpleServer, '\0', sizeof(simpleServer));
+    simpleServer.sin_family = AF_INET;
+    // inet_addr(argv[2], &simpleServer.sin_addr.s_addr);
+    simpleServer.sin_addr.s_addr = inet_addr(argv[1]);
+    simpleServer.sin_port = htons(simplePort);
+
+    /*  connect to the address and port with our socket  */
+    returnStatus = connect(simpleSocket, (struct sockaddr *)&simpleServer,
+                           sizeof(simpleServer));
+
+    if (returnStatus == 0)
+    {
+        fprintf(stderr, "Connect successful!\n");
+    }
+    else
+    {
+        fprintf(stderr, "Could not connect to address!\n");
+        close(simpleSocket);
+        exit(1);
+    }
+
+    // Inviando il numero di iterazioni al server
+    write(simpleSocket, iterationsServer, strlen(iterationsServer));
+
+    // Aspettando l'ACK
+    read(simpleSocket, valueToReceive, sizeof(valueToReceive));
+    printf("%s\n", valueToReceive);
+
+    int iterations = atoi(iterationsServer);
+    for (int i = 0; i < iterations; ++i)
+    {
+        clean_buffer((void *) valueToReceive, sizeof(valueToReceive));
+        printf("Inserire il valore da voler inviare al server: ");
+        scanf("%s", valueToSend);
+        write(simpleSocket, valueToSend, strlen(valueToSend));
+        read(simpleSocket, valueToReceive, sizeof(valueToReceive));
+        printf("\nEcho: %s\n", valueToReceive);
+    }
+    close(simpleSocket);
+    return 0;
+}
diff --git a/Reti/Laboratorio/Assigment4/EchoServer3/makefile b/Reti/Laboratorio/Assigment4/EchoServer3/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..f0ddf2785d27023f6a46168567b61136c6fc91b9
--- /dev/null
+++ b/Reti/Laboratorio/Assigment4/EchoServer3/makefile
@@ -0,0 +1,10 @@
+all: client server
+
+client: client.c
+	gcc client.c -o client
+
+server: server.c
+	gcc server.c -o server
+
+clean:
+	rm -f client server
diff --git a/Reti/Laboratorio/Assigment4/EchoServer3/server b/Reti/Laboratorio/Assigment4/EchoServer3/server
new file mode 100755
index 0000000000000000000000000000000000000000..c74259722a9539a0f3d04948bf995c13e76a3e20
Binary files /dev/null and b/Reti/Laboratorio/Assigment4/EchoServer3/server differ
diff --git a/Reti/Laboratorio/Assigment4/EchoServer3/server.c b/Reti/Laboratorio/Assigment4/EchoServer3/server.c
new file mode 100644
index 0000000000000000000000000000000000000000..a843b51b1431e1c3fb5a1d8b766cdf2a55f79c66
--- /dev/null
+++ b/Reti/Laboratorio/Assigment4/EchoServer3/server.c
@@ -0,0 +1,137 @@
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+// const char MESSAGE[] = "Guess who's back!\n";
+
+void clean_buffer(void* buffer, size_t buffer_size){ 
+    char* bufferChar = (char *) buffer;
+    for(size_t i = 0; i < buffer_size; ++i){
+        bufferChar[i] = '\0';
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    int simpleSocket = 0;
+    int simplePort = 0;
+    int returnStatus = 0;
+    struct sockaddr_in simpleServer;
+
+    if (argc < 1 || argc > 2)
+    {
+        fprintf(stderr, "Usage: %s <port>\n", argv[0]);
+        exit(1);
+    }
+
+    simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+    if (simpleSocket == -1)
+    {
+
+        fprintf(stderr, "Could not create a socket!\n");
+        exit(1);
+    }
+    else
+    {
+        fprintf(stderr, "Socket created!\n");
+    }
+
+    /* retrieve the port number for listening */
+    if (argc == 2)
+    {
+        simplePort = atoi(argv[1]);
+        if (simplePort < 10000 || simplePort > 12000)
+        {
+            fprintf(stderr, "Port must be in range [10000, 12000]\n");
+            exit(1);
+        }
+    }
+    else
+    {
+        srand(time(NULL));
+        simplePort = (rand() % 1999) + 10000;
+    }
+
+    /* setup the address structure */
+    /* use INADDR_ANY to bind to all local addresses  */
+    memset(&simpleServer, '\0', sizeof(simpleServer));
+    simpleServer.sin_family = AF_INET;
+    simpleServer.sin_addr.s_addr = htonl(INADDR_ANY);
+    simpleServer.sin_port = htons(simplePort);
+
+    /*  bind to the address and port with our socket */
+    returnStatus = bind(simpleSocket, (struct sockaddr *)&simpleServer,
+                        sizeof(simpleServer));
+
+    if (returnStatus == 0)
+    {
+        fprintf(stderr, "Bind completed on port %d!\n", simplePort);
+    }
+    else
+    {
+        fprintf(stderr, "Could not bind to address!\n");
+        close(simpleSocket);
+        exit(1);
+    }
+
+    /* lets listen on the socket for connections      */
+    returnStatus = listen(simpleSocket, 5);
+
+    if (returnStatus == -1)
+    {
+        fprintf(stderr, "Cannot listen on socket!\n");
+        close(simpleSocket);
+        exit(1);
+    }
+
+    struct sockaddr_in clientName = {0};
+    int simpleChildSocket = 0;
+    int clientNameLength = sizeof(clientName);
+
+    /* wait here */
+    while(1){
+        simpleChildSocket =
+            accept(simpleSocket, (struct sockaddr *)&clientName, &clientNameLength);
+
+        if (simpleChildSocket == -1)
+        {
+            fprintf(stderr, "Cannot accept connections!\n");
+            close(simpleSocket);
+            exit(1);
+        }
+
+        char bufferRead[256] = {'\0'};
+        read(simpleChildSocket, bufferRead, sizeof(bufferRead));
+        printf("Num Iterazioni: %s\n", bufferRead);
+        int iterations = atoi(bufferRead);
+
+        //Send ACK
+        char bufferWrite[256] = {'\0'};
+        snprintf(bufferWrite, sizeof(bufferWrite), "ACK");
+        write(simpleChildSocket, bufferWrite, sizeof(bufferWrite));
+
+
+        for (int i = 0; i < iterations; ++i)
+        {
+            clean_buffer((void *) bufferRead, sizeof(bufferRead));
+            clean_buffer((void *) bufferWrite, sizeof(bufferWrite));
+
+            char bufferRead[256] = {'\0'};
+            // Read message from client
+            read(simpleChildSocket, bufferRead, sizeof(bufferRead));
+            printf("\tReceived: %s\n", bufferRead);
+            char bufferWrite[256] = {'\0'};
+            snprintf(bufferWrite, sizeof(bufferWrite), "%s", bufferRead);
+            write(simpleChildSocket, bufferWrite, sizeof(bufferWrite));
+        }
+        close(simpleChildSocket);
+        }
+    close(simpleSocket);
+    return 0;
+}