C TCP/IP Reliable Transmission project not reliable

Use and complete the template provided. The entire template must be completed. If you don't, your post may be deleted!

  1. The problem statement, all variables and given/known data:

We must do the following for a massive coding project that is due at 12:20PM on Monday, July 22, 2013. We are to do the following (from the project writeup):

You are required to implement a socket based file
transmission program that runs on top of TCP/IP.
This can be divided into two phases:

  1. Secure communication between two processes, e.g., A and B, with
    error-handling using the Internet checksum algorithm for error detection.
  2. The Stop-and-Wait (SW) protocol discussed in class.

The following, at a minimum, must be
prompted for: [for the user to enter in]
(a) Size of packet
(b) Timeout interval (user-specified or ping-calculated)
(c) Size of sliding window
(d) Range of sequence numbers
(e) Situational Errors (none, randomly generated, or user-specified, i.e., drop
packets 2, 4, 5, lose acks 11, etc.)

File formats that must transfer over can be of any type,
e.g., .txt, .doc, .mov, .jpg, .exe, etc.

The information provided in the client (sender) window should include, but not
limited to:
Packet sequence number of packet sent.
Packet (sequence number) that timed out
Packet that was re-transmitted.
All packets in the current window.
Acks received.
Which packets are damaged, .i.e., deliberately trigger a
checksum error on the receiver side.
Information to be provided by the receiver:
Packets (sequence number) received.
Damaged packet(s) (checksum error should match
corresponding damaged packet from sender window).
Packets in the current receiver window.
Packets (duplicated) that are discarded.
Ack packets that are sent.
� Frames arriving out of order should be re-sequenced before assembly.

We are also required to ensure the md5 sums match for both the source and destination files and test our code with a 1GB file (to stress test it, the professor has said "I will try to break your code").

  1. Relevant commands, code, scripts, algorithms:

"assignment1.c"

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <arpa/inet.h> 
#include <sys/wait.h> 
#include <signal.h> 
#include <time.h> 
#include <semaphore.h> 
#include <fcntl.h> 
 
#define PORT 6789  // the port users will be connecting to 
#define BACKLOG 10   // how many pending connections queue will hold 
#define BUFFER_SIZE 1024 
 
int user, permPacketSize, timeoutType, timeoutInterval, sitErr; 
sem_t sem_transfer; 
 
/***********************************************************************************/ 
/***************************                          ******************************/ 
/***************************         SERVER           ******************************/ 
/***************************                          ******************************/ 
/***********************************************************************************/ 
int runServer() 
{ 
    int sock, msgsock, sin_size; // listen on sock, new connection on msgsock 
    struct sockaddr_in server;   // socket struct for server connection 
    struct sockaddr_in client;   // socket struct for client connection 
    char fromClient[BUFFER_SIZE];  // String from client 
    char toClient[BUFFER_SIZE];  // String sent to client 
    int temp;                     // temp int for calculations 
    int packetSize; 
    unsigned int seqNum = 0; 
    sem_init(&sem_transfer, 0, 1);   // initialize semaphore to 1 
    int fdServer; 
    int bytes_read, bytes_written; 
 
    /* Open a socket */ 
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
        perror("socket"); 
        exit(1); 
    } 
 
    /* Fill out server sockaddr_in struct */ 
    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = INADDR_ANY; 
    server.sin_port = htons(PORT); 
           
    /* Bind */ 
    if (bind(sock, (struct sockaddr *) &server, sizeof(server)) == -1) { 
        perror("bind"); 
        exit(2); 
    } 
 
    /* Listen w/ max queue of defined BACKLOG value */ 
    if (listen(sock, BACKLOG) == -1) { 
        perror("listen"); 
        exit(3); 
    } 
 
    sin_size = sizeof(struct sockaddr_in); 
 
    if ((msgsock = accept(sock, (struct sockaddr *)&client, &sin_size)) == -1) { 
        perror("accept"); 
    } 
 
    // get file to copy 
    char filename_received[BUFFER_SIZE]; 
     
    if (recv(msgsock, filename_received, BUFFER_SIZE,0) < 0){ 
        perror("Aborting"); 
        close(msgsock); 
        exit(4); 
    } 
    fprintf(stderr, "file to be copied: %s\n",filename_received); 
    char *copy; 
    copy = (char*) malloc (sizeof(char)*1024); 
    strcpy(copy, filename_received); 
        if  ( (fdServer = open (copy,  O_RDONLY))  == -1) { 
            perror ( "Error in opening the input file:"); 
            exit (1); 
        } 
    free(copy); 
     
    // Determine lowest packet size between client and server 
    sprintf(toClient, "%d", permPacketSize); 
    send(msgsock, toClient, sizeof(toClient),0); 
 
    if (recv(msgsock, fromClient, BUFFER_SIZE,0) < 0){ 
        perror("Aborting"); 
        close(msgsock); 
        exit(4); 
    } 
     
    temp = atoi(fromClient); 
 
    if (temp < permPacketSize){ 
        packetSize = temp; 
    } 
    else { 
        packetSize = permPacketSize; 
    } 
 
    fprintf(stderr, "The agreed upon packet size is %d\n", packetSize); 
    while (1) 
    { 
        void* buffer = (void*) malloc (packetSize); 
 
        bytes_read = read(fdServer, buffer, packetSize); 
        if (bytes_read == 0){ 
            break; 
        } 
         
        void *p = buffer; 
        while (bytes_read > 0){ 
            bytes_written = write(msgsock, p, bytes_read); 
            bytes_read -= bytes_written; 
            p += bytes_written; 
        } 
 
        free(buffer); 
 
        fprintf(stderr, "sending %d\n", seqNum); 
        seqNum++; 
    } 
    sprintf(toClient, "FINISHED\n"); 
    send(msgsock, toClient, sizeof(toClient),0); 
    // close all open fd's and sockets 
    close(msgsock); 
    close(sock); 
    close(fdServer); 
}   
 
/***********************************************************************************/ 
/***************************                          ******************************/ 
/***************************         CLIENT           ******************************/ 
/***************************                          ******************************/ 
/***********************************************************************************/ 
 
int runClient() 
{ 
    int sock;                    // fd for socket connection 
    struct sockaddr_in server;   // Socket info. for server 
    struct hostent *host;        // Server info   
    char selection[BUFFER_SIZE]; // User's input 
    char toServer[BUFFER_SIZE];   // String sent to server 
    char fromServer[BUFFER_SIZE];  // String rec'd from server 
    int temp;                     // temp int for calculations 
    int packetSize; 
    unsigned int ackNum = 0; 
    char* userInput; 
    userInput = (char*) malloc (sizeof(toServer)); 
    int fdClient; 
    int bytes_read, bytes_written; 
 
    // get server address 
    fprintf(stderr, "Enter the address of the server.\n"); 
    scanf("%s", userInput); 
 
    // Fill out sockaddr struct 
    server.sin_family = AF_INET; 
    if ((host = gethostbyname(userInput)) == NULL){ 
        printf("Unknown host.\n"); 
        exit(1); 
    } 
    server.sin_family = host->h_addrtype; 
    memcpy((char *) &server.sin_addr.s_addr, host->h_addr_list[0], host->h_length); 
    server.sin_port = htons((u_short) PORT); 
 
  // Create socket 
      if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){ 
        printf("Unable to open socket\n"); 
        perror("Aborting"); 
        exit(1); 
      } 
 
      // Try to connect 
      if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0){ 
        printf("Unable to connect to %s\n", userInput); 
        perror("Aborting"); 
        exit(1); 
      } 
 
    // request file to copy 
    printf("Enter a file name:\n"); 
    scanf("%s",userInput); 
    fprintf(stderr, "You entered: %s\n",userInput); 
    char filename_buf[BUFFER_SIZE]; 
    strcpy(filename_buf, userInput); 
 
    if (send(sock, filename_buf, sizeof(filename_buf),0) <0) 
    { 
        perror("Aborting"); 
        close(sock); 
        exit(42);         
    } 
 
    if  ( (fdClient = open (userInput, (O_WRONLY | O_CREAT),  0740)) == -1 ) 
    {  
            perror ( "Error in creating the output file:"); 
            exit (11); 
    } 
 
    free(userInput); 
 
    // Determine lowest packet size between client and server 
    sprintf(toServer, "%d", permPacketSize); 
    send(sock, toServer, sizeof(toServer),0); 
 
    if (recv(sock, fromServer, BUFFER_SIZE,0) < 0) 
    { 
        perror("Aborting"); 
        close(sock); 
        exit(4); 
    } 
 
    temp = atoi(fromServer); 
 
    if (temp < permPacketSize){ 
        packetSize = temp; 
    } 
    else { 
        packetSize = permPacketSize; 
    } 
    fprintf(stderr, "The agreed upon packet size is %d\n", packetSize); 
 
    while(1) 
    { 
        void* buffer = (void*) malloc (packetSize); 
 
        bytes_read = read(sock, buffer, packetSize); 
        if (bytes_read == 0){ 
            break; 
        } 
     
        void *p = buffer; 
        while (bytes_read > 0){ 
            bytes_written = write(fdClient, p, bytes_read); 
            bytes_read -= bytes_written; 
            p += bytes_written; 
        } 
 
        free(buffer); 
         
        fprintf(stderr, "receiving %d\n", ackNum); 
        ackNum++; 
    } 
    close(sock); 
    printf("All done. Connection to server terminated. Exiting...\n"); 
} 
 
 
/***********************************************************************************/ 
/***************************                          ******************************/ 
/***************************          MAIN            ******************************/ 
/***************************                          ******************************/ 
/***********************************************************************************/ 
 
int main(int argc, char *argv[]) 
{     
 
    // determine client or server 
    fprintf(stderr, "\nWelcome to the Reliable Transmission Project.\n"); 
    fprintf(stderr, "Please make the following numerical selections.\n\n"); 
    fprintf(stderr, "0) Server\n"); 
    fprintf(stderr, "1) Client\n"); 
     
    scanf("%d", &user); 
 
    if (user == 0){ 
        fprintf(stderr, "You have chosen to be the server.\n"); 
    } 
    else{ 
        fprintf(stderr, "You have chosen to be the client.\n"); 
    } 
 
    // determine packet size 
    fprintf(stderr, "\nPlease enter the packet size you would like to use (in bytes).\n"); 
    scanf("%d", &permPacketSize); 
    fprintf(stderr, "You have chosen a packet size of %d bytes.\n", permPacketSize); 
 
    // determine how to calculate timeout interval 
    fprintf(stderr, "\nWould you like the timeout interval to be determined manually or dynamically?\n\n"); 
    fprintf(stderr, "0) Set timeout interval manually\n"); 
    fprintf(stderr, "1) Automatic time interval\n"); 
 
    scanf("%d", &timeoutType); 
 
    if (timeoutType == 0){ 
        fprintf(stderr, "What would you like the timeout interval to be (in milliseconds)?\n"); 
        scanf("%d", &timeoutInterval); 
        fprintf(stderr, "You have chosen a timeout interval of %d milliseconds.\n", timeoutInterval); 
    } 
    else{ 
        fprintf(stderr, "The timeout interval will be automatically ping-calculated.\n"); 
        timeoutInterval = 4213; 
    } 
 
/***************************************************************** 
****************************************************************** 
 
    // determine situational errors 
    fprintf(stderr, "\nDo you want to introduce situational errors?\n\n"); 
    fprintf(stderr, "0) No\n"); 
    fprintf(stderr, "1) Yes\n"); 
 
    scanf("%d", &sitErr); 
 
    if (sitErr == 0){ 
        fprintf(stderr, "No situational errors will be used.\n"); 
    } 
    else{ 
        fprintf(stderr, "Which situational error would you like to introduce?\n"); 
        fprintf(stderr, "1) Drop packets\n"); 
        fprintf(stderr, "2) Lose ACKs\n"); 
        fprintf(stderr, "3) Send damaged packets\n"); 
        fprintf(stderr, "4) Random\n"); 
        scanf("%d", &sitErr); 
 
        if(sitErr == 1){ 
            fprintf(stderr, "You have chosen to have some packets get dropped.\n");         
        } 
        else if(sitErr == 2){ 
            fprintf(stderr, "You have chosen to lose some ACK commands.\n"); 
        } 
        else if(sitErr == 3){ 
            fprintf(stderr, "You have chosen to send some damaged packets.\n"); 
        } 
        else{ 
            fprintf(stderr, "You have chosen to have a random error selected.\n"); 
            srand((unsigned)time(NULL)); 
            sitErr = (rand() % 3 + 1); 
            if(sitErr==1) 
                fprintf(stderr, "You will have some packets get dropped.\n"); 
            else if(sitErr==2) 
                fprintf(stderr, "You will lose some ACK commands.\n"); 
            else 
                fprintf(stderr, "You will send some damaged packets.\n"); 
        } 
    } 
 
********************************************** 
********************************************/ 
 
    // all settings are entered, run client/server 
    if(user){ 
        runClient(); 
    } 
    else{ 
        runServer(); 
    } 
 
    return 0; 
}

"send.txt"

SEND ME...
  1. The attempts at a solution (include all code and scripts):

When I ran this, I got the following printouts (these are abbreviated to not take up ten miles of screen space):

(server side)

Welcome to the Reliable Transmission Project. 
Please make the following numerical selections. 
 
0) Server 
1) Client 
0 
You have chosen to be the server. 
 
Please enter the packet size you would like to use (in bytes). 
50 
You have chosen a packet size of 50 bytes. 
 
Would you like the timeout interval to be determined manually or dynamically? 
 
0) Set timeout interval manually 
1) Automatic time interval 
1 
The timeout interval will be automatically ping-calculated. 
file to be copied: project.pdf 
The agreed upon packet size is 50 
sending 0 
sending 1 
sending 2 
sending 3 
sending 4 
[...]
sending 1820 
sending 1821 
sending 1822 
sending 1823

(client side)

Welcome to the Reliable Transmission Project. 
Please make the following numerical selections. 
 
0) Server 
1) Client 
1 
You have chosen to be the client. 
 
Please enter the packet size you would like to use (in bytes). 
50 
You have chosen a packet size of 50 bytes. 
 
Would you like the timeout interval to be determined manually or dynamically? 
 
0) Set timeout interval manually 
1) Automatic time interval 
1 
The timeout interval will be automatically ping-calculated. 
Enter the address of the server. 
127.0.0.1 
Enter a file name: 
project.pdf 
You entered: project.pdf 
The agreed upon packet size is 50 
receiving 0 
receiving 1 
receiving 2 
receiving 3 
receiving 4 
[...]
receiving 1840 
receiving 1841 
receiving 1842 
receiving 1843 
All done. Connection to server terminated. Exiting... 

Running md5 checksums on both I get (after testing the program with our project writeup, project.pdf):

$ md5sum project.pdf
e1febbee4b614140677dd7c8a221f5c6  project.pdf
$ md5sum copy_of_project.pdf
9a6003fb91d80209d717c646ab3012ff  copy_of_project.pdf

These don't match, so the file clearly does not copy correctly. Even though I am able to copy over files of different types, and they work correctly (I tried it with an mp3, it played just like the original file), I am believing that extra bytes are being inserted in the file transfer somewhere. I am not sure if the checksum has something to do with this. I know I have to implement it somewhere, but I am not certain where to do this, or if the checksum even checks to see if the original bytes that are passed in from the sender in each packet are the same bytes that get to the receiver? You can try my code with any of your own files, and if it's running like it did with me, your copied file will be bigger than your original file.

I've been working on this for a few weeks and have not been able to discern what is going on? There is a lot of stuff we still have yet to do (like deliberately insert damaged packets or cause them to get lost, or acks to get lost), but I'm stuck with about 9 days left before it is due (what a way to spend summer, slaving at a massive pig of coding, eh?).

Can anyone help me out at all? Thanks!

  1. Complete Name of School (University), City (State), Country, Name of Professor, and Course Number (Link to Course):

University of Minnesota, Twin Cities; Minneapolis, MN, USA, Professor Jack Tan, CSCI 4211: Csci4211/Csci5211-Computer Networks

Note: Without school/professor/course information, you will be banned if you post here! You must complete the entire template (not just parts of it).

Never mind, I had figured it out. It involved simply moving the fprintf calls in the main while loops in both runClient() and runServer() before I wrote the "bytes_read" to "bytes_written" and sent them back and forth. No assistance needed here now!

1 Like