Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending files from client to server using sockets in C

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;

   }
like image 649
jimo Avatar asked May 25 '15 14:05

jimo


People also ask

How do you send data from client to server in socket programming?

Create a socket with the socket() system call. Initialize the socket address structure as per the server and connect the socket to the address of the server using the connect() system call. Receive and send the data using the recv() and send(). Close the connection by calling the close() function.

What does socket () do in C?

The socket() function shall create an unbound socket in a communications domain, and return a file descriptor that can be used in later function calls that operate on sockets. The socket() function takes the following arguments: domain. Specifies the communications domain in which a socket is to be created.

Can sockets send and receive?

Once connected, a TCP socket can only send and receive to/from the remote machine. This means that you'll need one TCP socket for each client in your application. UDP is not connection-based, you can send and receive to/from anyone at any time with the same socket.


2 Answers

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;
}
like image 95
Sir Jo Black Avatar answered Oct 17 '22 11:10

Sir Jo Black


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

like image 29
user3629249 Avatar answered Oct 17 '22 10:10

user3629249