Gaurav K
Gaurav K

Reputation: 2975

Sending a file content to a server: Socket

My code reads from a file line by line and sends it to a server.

client.c

int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    FILE* pFile;
    char* line = NULL;
    //char buffer[256];
    char* buffer;
    int len;



    if (argc < 3) {
       fprintf(stderr,"usage %s hostname port\n", argv[0]);
       exit(0);
    }



   pFile = fopen ("myfile.txt","r");
   if (pFile==NULL)
   {
        printf("Error reading temp file\n");
        exit (1);
       }

    portno = atoi(argv[2]);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if (sockfd < 0) 
        error("ERROR opening socket");
    server = gethostbyname(argv[1]);
    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;

    bcopy((char *)server->h_addr, 
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);

    serv_addr.sin_port = htons(portno);
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
    error("ERROR connecting");


//loop  
     while (!feof(pFile)) {
    //printf("Please enter the message: ");
    line = readLine(pFile, line);
    len=strlen(line);
    buffer= (char*) malloc((len+1)*sizeof(char));
    bzero(buffer,len);
    memcpy(buffer,line,len+1);
   // fgets(buffer,len,pFile);
    printf("%s\n", buffer);
    n = write(sockfd,buffer,strlen(buffer)+1);
    if (n < 0) 
        error("ERROR writing to socket");
    free(buffer);    
    free(line); 
    }   



    buffer= (char*) malloc(2048*sizeof(char));   
    bzero(buffer,2048);
    n = read(sockfd,buffer,2048);

    if (n < 0) 
         error("ERROR reading from socket");
    printf("%s\n",buffer);

    free(buffer);
    fclose (pFile);
    close(sockfd);
    return 0;
}

And

    /* A simple server in the internet domain using TCP
   The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>



void error(const char *msg)
{
    perror(msg);
    exit(1);
}



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


 int sockfd, newsockfd, portno;
 socklen_t clilen;
 char buffer[2048];
 struct sockaddr_in serv_addr, cli_addr;
 int n;


 if (argc < 2) {
     fprintf(stderr,"ERROR, no port provided\n");
     exit(1);
 }


 sockfd = socket(AF_INET, SOCK_STREAM, 0);
 if (sockfd < 0) 
    error("ERROR opening socket");
    else
    printf("Socket connected\n");


 bzero((char *) &serv_addr, sizeof(serv_addr));
 portno = atoi(argv[1]);
 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = INADDR_ANY;
 serv_addr.sin_port = htons(portno);
 if (bind(sockfd, (struct sockaddr *) &serv_addr,
          sizeof(serv_addr)) < 0) 
          error("ERROR on binding");
 listen(sockfd,5);
 clilen = sizeof(cli_addr);
 newsockfd = accept(sockfd, 
             (struct sockaddr *) &cli_addr, 
             &clilen);
 if (newsockfd < 0) 
      error("ERROR on accept");

 printf("Data Receieved by client: \n");

  bzero(buffer,2048);
  n=read(newsockfd,buffer,2048);

    if (n < 0) error("ERROR reading from socket");
    printf("%s\n",buffer);



  n = write(newsockfd,"Server received the message",18); 
  if (n < 0) 
      error("ERROR writing to socket");



 close(newsockfd);
 close(sockfd);
 return 0; 

}

The problem is that the server reveives a few lines and misses a few. Not able to figure out what is wrong. Can some one help?

Client Side
[gaurav1.k@DELL-BUILD03 Socket]$ gcc -Wall client.c -o client.exe
[gaurav1.k@DELL-BUILD03 Socket]$ ./client.exe localhost 8000
I am line number One,am I?
Here comes line number Two.
Will you welcome, Line number Three? And I am your Friend.
I am here, It is me - Line number Four.
Hello All, I am line number Five, am I? Yes I am.
It is over, because I am line number six.
Server received th
[gaurav1.k@DELL-BUILD03 Socket]$

Server Side:
[gaurav1.k@DELL-BUILD03 Socket]$ gcc -Wall server.c -o server.exe
[gaurav1.k@DELL-BUILD03 Socket]$ ./server.exe 8000
Socket connected
Data Receieved by client:
I am line number One,am I?
[gaurav1.k@DELL-BUILD03 Socket]$

The content of file to be read is:

I am line number One,am I?
Here comes line number Two.
Will you welcome, Line number Three? And I am your Friend.
I am here, It is me - Line number Four.
Hello All, I am line number Five, am I? Yes I am.
It is over, because I am line number six.

Upvotes: 0

Views: 1862

Answers (4)

Martin James
Martin James

Reputation: 24847

On top of the failure to properly account for the returns from system calls, as described by other posters, there is:

bzero(buffer,2048);
n=read(newsockfd,buffer,2048)
..
printf("%s\n",buffer);

If the read() returns 2048 bytes, the printf can UB as it tries to find a non-existent null after the end of the buffer. Either allocate/clear 2049 of read 2047, and even that will only work well for transferring plain ASCII text files, (ie files with no embedded nulls).

Upvotes: 0

Wolfgang Ziegler
Wolfgang Ziegler

Reputation: 1685

For a scenario like this you usually want to implement a kind of communication protocol.

Most importantly, the server needs to know how many bytes it has to read to receive the whole content. So usually, you transfer the message size as the first part of your message (header). Then the server knows how many bytes to receive after that to consume the actual payload data.

Upvotes: 3

Sathish
Sathish

Reputation: 3870

The problem is multiple write at the client side, but only one read at the server side. How?

For every line the client will write into the socket, that is multiple write(you are using write in a loop), but in server you are having one read, that is single read(no loop's, so it will read only the first line).

For first line, you are reading at server side. But for second line the client is writing, but your server have no read statement(first read is already executed). Due to this you wont receive the full message

A simple solution is write the whole file content at a time, not line by line and read it.

Try the below change also-

n = write(newsockfd,"Server received the message",50); // Increase the size

Upvotes: 1

Michael Aaron Safyan
Michael Aaron Safyan

Reputation: 95449

It looks like the problem is that you don't check the result of the read and write functions, which can fail in partial success states, indicating the number of bytes they've successfully transferred. In general, you need to wrap these functions in a loop that repeats until the entire buffer has been read/written.

Upvotes: 0

Related Questions