linux - Why will my C socket file transfer (server/client) program run correctly only once? -


this first time post on stack overflow. apologize if have not followed protocol correctly.

i have simple c socket program client , server component. program sends file client on 1 vm server on vm. program works , file sends first time.

however, when try run program second time, file not seem transferred. through investigation, have found that, after rebooting vms, program works again. why happening?

here server code:

newfileserver.c

/* server code */ /* todo : modify meet need */ #include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/sendfile.h> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <arpa/inet.h> #include <unistd.h> #include <netinet/in.h>  #define port_number     5000 #define server_address  "10.20.20.55" #define filename    "/home/saul/m2.py"  int main(int argc, char **argv) {         int server_socket;         int peer_socket;         socklen_t sock_len;         ssize_t len;         struct sockaddr_in server_addr;         struct sockaddr_in peer_addr;         ssize_t rec;         int sent_bytes = 0;         char file_size[512];         int file_size_a;         struct stat file_stat;         off_t offset;         int remain_data;         char buffer[bufsiz];         file *received_file;         int closed = 0;         int fclosed = 0;          /* create server socket */         server_socket = socket(af_inet, sock_stream, 0);         if (server_socket == -1)         {                 fprintf(stderr, "error creating socket --> %s", strerror(errno));                  exit(exit_failure);         }          printf("socket created successfully: %d\n", server_socket);         /* zeroing server_addr struct */         memset(&server_addr, 0, sizeof(server_addr));         /* construct server_addr struct */         server_addr.sin_family = af_inet;         //inet_pton(af_inet, server_address, &(server_addr.sin_addr));         inet_pton(af_inet, server_address, &(server_addr.sin_addr));         server_addr.sin_port = htons(port_number);          /* bind */         if ((bind(server_socket, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))) == -1)         {                 fprintf(stderr, "error on bind --> %s", strerror(errno));                  exit(exit_failure);         }          printf("binding socket done\n");         /* listening incoming connections */         if ((listen(server_socket, 5)) == -1)         {                 fprintf(stderr, "error on listen --> %s", strerror(errno));                  exit(exit_failure);         }          printf("no error on listen\n");          sock_len = sizeof(struct sockaddr_in);         peer_socket = accept(server_socket, (struct sockaddr *)&peer_addr, &sock_len);          printf("\naccept has been performed\n");          if (peer_socket < 0)         {                 fprintf(stderr, "error on accept --> %s", strerror(errno));                  exit(exit_failure);         }         fprintf(stdout, "accept peer --> %s\n", inet_ntoa(peer_addr.sin_addr));           /* receive file */         /*____________________________________________________*/         /* receiving file size */          len = recv(peer_socket, buffer, bufsiz, 0);         if(len <= 0)         {             printf("\neither error has occurred or there no data in recv: %d\n", len);         }         printf("\nthe message has been received , length of %d\n", len);         len = 5;         file_size_a = atoi(buffer);         printf("\nthe size of file_size_a %d\n", file_size_a);         //fprintf(stdout, "\nfile size : %d\n", file_size);          received_file = fopen(filename, "w");         if (received_file == null)         {                 fprintf(stderr, "failed open file foo --> %s\n", strerror(errno));                  exit(exit_failure);         }          remain_data = file_size_a;          while (((len = recv(peer_socket, buffer, bufsiz, 0)) > 0) && (remain_data > 0))         {                 fwrite(buffer, sizeof(char), len, received_file);                 remain_data -= len;                 fprintf(stdout, "receive %d bytes , hope :- %d bytes\n", len, remain_data);         }          printf("len after skipping while loop %d\n", len);          fclosed = fclose(received_file);          if(fclosed != 0)         {             fprintf(stderr, "failed close received_file --> %s\n", strerror(errno));                  exit(exit_failure);         }         else         {             printf("\nreceived_file closed\n");         }          /*_____________________________________________________*/           closed = close(peer_socket);         if(closed == -1)         {             fprintf(stderr, "failed close peer_socket --> %s\n", strerror(errno));                  exit(exit_failure);         }         else         {             printf("\npeer socket closed\n");         }          closed = close(server_socket);         if(closed == -1)         {             fprintf(stderr, "failed close server_socket --> %s\n", strerror(errno));                  exit(exit_failure);         }         else         {             printf("\nserver socket closed\n");         }          printf("\nprocess id is: %d\n", getpid());          return 0; } 

here client code:

newfileclient.c

/* client code */ /* todo : modify meet need */ #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <arpa/inet.h> #include <unistd.h> #include <netinet/in.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/sendfile.h>  #define port_number     5000 #define server_address  "10.20.20.55" #define filename        "/home/saul2/test.py"  int main(int argc, char **argv) {         int client_socket;         ssize_t len;         struct sockaddr_in remote_addr;         char buffer[bufsiz];         char ip[bufsiz];         //int file_size;         char file_size[512];         file *received_file;         int remain_data = 0;         int pnum = 0;         int fd;         struct stat file_stat;         socklen_t       sock_len;         struct sockaddr_in      peer_addr;         off_t offset;         int sent_bytes = 0;         int closed = 0;         int closefd = 0;          /* zeroing remote_addr struct */         memset(&remote_addr, 0, sizeof(remote_addr));          /* construct remote_addr struct */         remote_addr.sin_family = af_inet;         inet_pton(af_inet, server_address, &(remote_addr.sin_addr));         remote_addr.sin_port = htons(port_number);          /* create client socket */         client_socket = socket(af_inet, sock_stream, 0);         if (client_socket == -1)         {                 fprintf(stderr, "error creating socket --> %s\n", strerror(errno));                  exit(exit_failure);         }          fprintf(stderr, "socket created %d\n", client_socket);         inet_ntop(af_inet, &(remote_addr.sin_addr), ip, bufsiz);         fprintf(stderr, "\nthe ip address converted %s \n", ip);         pnum = ntohs(remote_addr.sin_port);         fprintf(stderr, "\nthe re-converted port number is, %d\n", pnum);           /* connect server */         if (connect(client_socket, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) == -1)         {                 fprintf(stderr, "error on connect --> %s\n", strerror(errno));                  exit(exit_failure);         }             /* send file */         /*______________________________________________*/         fd = open(filename, o_rdonly);         if (fd == -1)         {                 fprintf(stderr, "error opening file --> %s", strerror(errno));                  exit(exit_failure);         }          /* file stats */         if (fstat(fd, &file_stat) < 0)         {                 fprintf(stderr, "error fstat --> %s", strerror(errno));                  exit(exit_failure);         }          fprintf(stdout, "file size: \n%d bytes\n", file_stat.st_size);          sock_len = sizeof(struct sockaddr_in);          sprintf(file_size, "%d", file_stat.st_size);          /* sending file size */         len = send(client_socket, file_size, sizeof(file_size), 0);         if (len < 0)         {               fprintf(stderr, "error on sending greetings --> %s", strerror(errno));                exit(exit_failure);         }          fprintf(stdout, "client sent %d bytes size\n", len);          offset = 0;         remain_data = file_stat.st_size;         /* sending file data */         while (((sent_bytes = sendfile(client_socket, fd, &offset, bufsiz)) > 0) && (remain_data > 0))         {                 fprintf(stdout, "1. client sent %d bytes file's data, offset : %d , remaining data = %d\n", sent_bytes, offset, remain_data);                 remain_data -= sent_bytes;                 fprintf(stdout, "2. client sent %d bytes file's data, offset : %d , remaining data = %d\n", sent_bytes, offset, remain_data);         }          closefd = close(fd);         if(closefd == -1)         {             fprintf(stderr, "failed close file --> %s\n", strerror(errno));                  exit(exit_failure);         }         else         {             printf("\nfile closed\n");         }          closed = close(client_socket);         if(closed == -1)         {             fprintf(stderr, "failed close client_socket --> %s\n", strerror(errno));                  exit(exit_failure);         }         else         {             printf("\nclient socket closed\n");         }          /*____________________________________________________*/           //close(client_socket);         printf("\nprocess id is: %d\n", getpid());           return 0; } 

initially, thought might because port left open. far can tell, code closes files , ports uses. have used netstat command:

netstat -atn 

to view open ports. found there indeed open port number 5000 on client side. had status "time_wait". after 2 minutes, port seems close itself. looked , seems normal behaviour port in process of closing.

interestingly, after port closes, program still not work , works after reboot. strange thing found couple of days ago, if waited 7-8 minutes after executing program first time , tried again, execute , file transferred. however, no longer works , thing fix problem system restart.

i know code far perfect there fundamental problem code causing issue?

many in advance help.

i editing post add output of program.

firstly, successful execution:

server output:

socket created successfully: 3 binding socket done no error on listen  accept has been performed accept peer --> 10.20.20.44  message has been received , length of 512  size of file_size_a 193 receive 193 bytes , hope :- 0 bytes len after skipping while loop 0  received_file closed  peer socket shutdown  server socket shutdown  process id is: 1397 

client output:

socket created 3  ip address converted 10.20.20.55  re-converted port number is, 5000 file size: 193 bytes client sent 512 bytes size 1. client sent 193 bytes file's data, offset : 193 , remaining data = 193 2. client sent 193 bytes file's data, offset : 193 , remaining data = 0  file closed  client socket shutdown  process id is: 1298 

now add output when execution unsuccessful.

server output:

socket created successfully: 3 binding socket done no error on listen  accept has been performed accept peer --> 10.20.20.44  message has been received , length of 705  size of file_size_a 193 len after skipping while loop 0  received_file closed  peer socket shutdown  server socket shutdown  process id is: 1398 

client output:

socket created 3  ip address converted 10.20.20.55  re-converted port number is, 5000 file size: 193 bytes client sent 512 bytes size 1. client sent 193 bytes file's data, offset : 193 , remaining data = 193 2. client sent 193 bytes file's data, offset : 193 , remaining data = 0  file closed  client socket shutdown  process id is: 1299 

i still have not solved issue.

thanks

it looks race condition. more works first time chance, because initialization times causes 2 client writes separately read on server. , on following runs, 2 writes read first server read.

the key here : 705 = 512 (header size) + 193 (file size).

the problematic lines here:

    /* receiving file size */      len = recv(peer_socket, buffer, bufsiz, 0); 

you read bufsiz bytes, when client should send @ 512 bytes message part. if client fast enough, has queued , data part concatenated in first read after 512 bytes of message. , of course, nothing left following reads , reach end of file , exit receiving loop.

you should write in newfileserver.c:

    /* receiving file size */      char file_size[512];     len = recv(peer_socket, file_size, sizeof(file_size), 0);     ...     file_size_a = atoi(file_size);     ... 

this ensures message read eats 512 bytes , leaves file data following reads.


Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -