5

The program is supposed to send the contents of a file from the client side to an output file on the server side. However, my code is working for few files and not working for most of the files. For example if I try to copy content of a file called morefood.txt to an output file say picolo.txt, nothing is copied.

Server code:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>

int main(int argc, char *argv[]){

  int fd =0, confd = 0;
  struct sockaddr_in serv_addr;

  char buff[1025];
  int num;

  fd = socket(AF_INET, SOCK_STREAM, 0);
  printf("Socket created\n");

  memset(&serv_addr, '0', sizeof(serv_addr));
  memset(buff, '0', sizeof(buff));

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port = htons(5000);

  bind(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
  listen(fd, 10);

  FILE* fp = fopen( "picolo.txt", "wb");

  if(fp == NULL){
      fprintf(stderr, "something went south");
      return 1;
  }

  while(1){

      confd = accept(fd, (struct sockaddr*)NULL, NULL);

      char recvbuff[10];

      int b = recv(confd, recvbuff, 10, 0);

      while(b>0)
     {
          fwrite(recvbuff, 1, b, fp);

          b = recv(confd, recvbuff, 10, 0);

     }
   close(confd);
  }

return 0;

}

Client code:

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>


int main(int argc, char *argv[]){

    int sfd =0, n=0;
    char rbuff[1024];

    struct sockaddr_in serv_addr;

    memset(rbuff, '0', sizeof(rbuff));
    sfd = socket(AF_INET, SOCK_STREAM, 0);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000);
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    FILE *fp = fopen("morefood.txt", "rb");

    if(fp == NULL){
        fprintf(stderr, "oh no!");
        return 1;
    }

    char sendbuffer[100];

    int b = fread(sendbuffer, 1, sizeof(sendbuffer), fp);

    while(!feof(fp)){
        send(sfd, sendbuffer, b, 0);
        b = fread(sendbuffer, sizeof(sendbuffer), 1, fp);
    }

    return 0;

   }
jimo
  • 430
  • 2
  • 7
  • 19
  • 1
    So you are saying that the functionality is depending on **FILE NAMES**?! [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Eugene Sh. May 25 '15 at 14:07
  • 1
    You should **really** handle **all possible** (error) cases `recv()` and `send()` can indicate (via their return value). Same for `connect()`, `bind()` and `accept()`. – alk May 25 '15 at 14:16
  • Note - always close the socket when done! – Martin James May 25 '15 at 15:02
  • It seems to me that this is a case where 'while ( !feof (file) )' is fine. – Martin James May 25 '15 at 15:03
  • The server receive buffer is a bit small:( – Martin James May 25 '15 at 15:06
  • @MartinJames buffer is not the problem I tried it. – jimo May 25 '15 at 15:19
  • 2
    feof() is rarely, if ever, the correct way to control a loop. – user3629249 May 25 '15 at 15:36
  • The use of buffers both in client and in server is bugged!!! :) – Sir Jo Black May 25 '15 at 16:26
  • 2
    regarding: ` fd = socket(AF_INET, SOCK_STREAM, 0)` the function: `socket()` can fail, then it returns a value < 0. The code should be checking for this condition and handling the error. One way to handle the error: `perror( "socket failed" ); exit( EXIT_FAILURE );` – user3629249 Sep 02 '20 at 02:48

3 Answers3

6

The issue is that both transmission and reception loop are bugged! I've modified them in a way that the codes run better, but I think there's a lot to modify to have a solid code!

Client:

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>

int main(int argc, char *argv[]){

    int sfd =0, n=0, b;
    char rbuff[1024];
    char sendbuffer[100];

    struct sockaddr_in serv_addr;

    memset(rbuff, '0', sizeof(rbuff));
    sfd = socket(AF_INET, SOCK_STREAM, 0);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000);
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    b=connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if (b==-1) {
        perror("Connect");
        return 1;
    }

    FILE *fp = fopen("prova.jpg", "rb");
    if(fp == NULL){
        perror("File");
        return 2;
    }

    while( (b = fread(sendbuffer, 1, sizeof(sendbuffer), fp))>0 ){
        send(sfd, sendbuffer, b, 0);
    }

    fclose(fp);
    return 0;

}

Server:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>

int main(int argc, char *argv[]){

    int fd =0, confd = 0,b,tot;
    struct sockaddr_in serv_addr;

    char buff[1025];
    int num;

    fd = socket(AF_INET, SOCK_STREAM, 0);
    printf("Socket created\n");

    memset(&serv_addr, '0', sizeof(serv_addr));
    memset(buff, '0', sizeof(buff));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(5000);

    bind(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    listen(fd, 10);

    while(1){
        confd = accept(fd, (struct sockaddr*)NULL, NULL);
        if (confd==-1) {
            perror("Accept");
            continue;
        }
        FILE* fp = fopen( "provacopy.jpg", "wb");
        tot=0;
        if(fp != NULL){
            while( (b = recv(confd, buff, 1024,0))> 0 ) {
                tot+=b;
                fwrite(buff, 1, b, fp);
            }

            printf("Received byte: %d\n",tot);
            if (b<0)
               perror("Receiving");

            fclose(fp);
        } else {
            perror("File");
        }
        close(confd);
    }

    return 0;
}
Sir Jo Black
  • 2,024
  • 2
  • 15
  • 22
2

this code, in the client:

char sendbuffer[100];

int b = fread(sendbuffer, 1, sizeof(sendbuffer), fp);

while(!feof(fp)){
    send(sfd, sendbuffer, b, 0);
    b = fread(sendbuffer, sizeof(sendbuffer), 1, fp);
}

is not a good way to send a 'nameless' file.

I suggest

while( 0< (byteCount = fread( sendbuffer, sizeof(sendbuffer), 1, fp) ) )
{
    send(sfd, sendbuffer, byteCount, 0);
}

however, for robustness

--client send a file name and total file size with recordNum 0
--server when receiving recordNum 0
  open the appropriate file name
  if successful open, send 'ack', maxRecordSize echo recordNum
  else send 'nak' echo recordNum
--client, on following records, 
  send byteCount, recordNum, data
--server respond with 'ack' for each received record
  when it is expected recordNum
  otherwise respond with 'nak' expected recordNum
--when client receives 'ack' send next record
--when client receives 'nak' resend prior record
--client, after all file sent, send file checksum with recordnum -1
--server, when receive recordNum -1 compares checksum, closes file
  responds with final 'ack' if checksum matches
  responds with final 'nak' if checksum does not match

This 'lockstep' communication, which is often used in the real world, will assure both ends of the communication know what is going on and will assure a successful file transfer,

This works for only one file being sent at a time. for multiple files being sent at the same time, the records will need another field, that indicates which file 'this' record is part of.

of course, all send/recv/open/connect/bind/ etc system function calls need to have the returned value(s) checked for errors

user3629249
  • 16,402
  • 1
  • 16
  • 17
0

Part to read from file in server

    .
    .  // Your other code
    .
    read(client, rbuff, sizeof(rbuff); //Getting file name from client
    printf("File wanted by client%s\n", textToRec);
    int filedesc = open(textToRec, O_RDONLY); //Opening the file
    struct stat sb;  //To get the size of file

    if (lstat(ruff, &sb) == -1) {
        exit(EXIT_FAILURE);
    }
    long long fsize;
    fsize = sb.st_size;
    if ((0 == filedesc)) {
        fprintf(stderr,"error in reading file");
        exit(-1);
    }
    write(client, fsize, sizeof(fsize)); //Sending Filesize
    read(filedesc, sendbuffer, fsize);  //Putting file in buffer
    write(client, sendbuffer, sizeof(sendbuffer));  //Sending buffer to client
    
    close(socketid);
    .
    .
    .  // Your code

Part on the client side:

   /* your code above */
    printf("file name sent...Now wait!\n");
// I am assuming you put filename in buff
    read(sock, buff,sizeof(buff)); //Receiving file size
    long long fsize = strtol(buff,NULL,10);
    read(sock, buff,sizeof(buff)); 
    /*It's better to use sizeof instead of actual number as you can change the size of buffer anytime without needing to change values everywhere */
    int filedesc;
    filedesc =
        open(textToSend, O_WRONLY | O_APPEND | O_CREAT, 0644);
    if (!filedesc) {
        printf("failed to create file\n");
        exit;
    }
    write(filedesc, buff, fsize);
    close(filedesc);
    close(confd);

Mohit Sharma
  • 338
  • 2
  • 13