2017-02-12 1 views
0

Я очень новичок в программировании сокетов, и у меня есть относительно мало знаний об этом. Задача Я ожидал сделать включает в себя следующие этапы:Передача файла сервера клиента в c, затруднение в получении содержимого файла

  • клиент посылает команду «список» на сервер
  • сервер выполнить «LS >> files.txt» и посылает files.txt к клиенту, чьи содержимое отображается на клиентском терминале
  • Клиент теперь отправляет имя файла (скажем, abc.txt) из отображаемых имен и желает сохранить его содержимое в скопированном файле, а также отобразить его на своем терминале.
  • клиент отправляет «конец» «для завершения соединения и, следовательно, выполнения программы.

Я написал код для этого, но клиент не получает данные, даже если сервер отправляет его соответствующим образом.

Код выглядит следующим образом:

SERVER

//SERVER 
#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(void) 
{ 
int listenfd = 0,k=0; 
int connfd = 0,nread,let; 
struct sockaddr_in serv_addr,client; 
char sendBuff[1025],buffer[50]; 
int numrv; 

listenfd = socket(AF_INET, SOCK_STREAM, 0); 
if(listenfd==-1) 
{ 
    printf("Error in socket creation"); 
    exit(1); 
} 
printf("Socket created successfully\n"); 
memset(&serv_addr, '0', sizeof(serv_addr)); 
memset(sendBuff, '0', sizeof(sendBuff)); 

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

k=bind(listenfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr)); 
if(k==-1) 
{ 
printf("Error in binding\n"); 
exit(1); 
} 
printf("Binded successfully\n"); 
printf("Waiting for client to connect\n"); 
if(listen(listenfd, 20) == -1) 
{ 
    printf("Failed to listen\n"); 
    exit(1); 
} 
printf("Connection established\n"); 
let=sizeof(client); 
connfd = accept(listenfd, (struct sockaddr*)&client ,&let); 
if(connfd==-1) 
{ 
printf("Error in temporary socket creation\n"); 
exit(1); 
} 
while(1) 
{ 
    strcpy(buffer,"end"); 
    printf("Waiting to receive\n"); 
    k=recv(connfd, buffer,50, 0); 
    FILE *fp2 = fopen(buffer,"r"); 
    if(k==-1) 
    { 
     printf("Error in receiving\n"); 
     exit(1); 
    } 
    /*---- Print the received message ----*/ 
    printf("Data received: %s\n",buffer); 
    if(strncmp(buffer,"end",3)==0) 
     { 
     printf("Connection terminated\n"); 
     break; 
     } 
    else if(strncmp(buffer,"list",4)==0) 
    { 
     FILE *fp = fopen("files.txt","w"); 
     system("ls>>files.txt"); 
     fclose(fp); 
     /* Open the file that we wish to transfer */ 
     FILE *fp1 = fopen("files.txt","r"); 
     if(fp==NULL) 
     { 
      printf("File open error"); 
      return 1; 
     } 
     /* Read data from file and send it */ 
     printf("Sending reply\n"); 
     while(1) 
     { 
      /* First read file in chunks of 256 bytes */ 
      unsigned char buff[256]; 
      nread = fread(buff,1,256,fp); 
      //printf("Bytes read %d \n", nread);   
      /* If read was success, send data. */ 
      printf("Sending contents of files.txt\n"); 
      if(nread > 0) 
      { 
       write(connfd, buff, nread); 
      } 
      // Either there was error, or we reached end of file. 
      if (nread < 256) 
      { 
       if (feof(fp)) 
        printf("Successfully sent\n"); 
       if (ferror(fp)) 
        printf("Error reading\n"); 
       break; 
      } 
     } 
     fclose(fp1); 
    } 
    else if(fp2!=NULL) 
    { 
    //Read data from file and send it 
    printf("Sending reply\n"); 
    while(1) 
     { 
     //First read file in chunks of 256 bytes 
     unsigned char buff[256]; 
     nread = fread(buff,1,256,fp2); 
     //printf("Bytes read %d \n", nread);   
     // If read was success, send data. 
     printf("Sending contents of %s\n",buffer); 
     if(nread > 0) 
     { 

      write(connfd, buff, nread); 
     } 

     // Either there was error, or we reached end of file. 

     if (nread < 256) 
     { 
      if (feof(fp2)) 
       printf("Successfully sent\n"); 
      if (ferror(fp2)) 
       printf("Error reading\n"); 
      break; 
     } 
     } 
    } 
    else 
    { 
     printf("Sending reply\n"); 
     write(connfd, "Unidentified command", 20); 
    } 
} 
close(connfd); 
exit(0); 
return 0; 
} 
//Reference://http://codereview.stackexchange.com/questions/43914/client-server-implementation-in-c-sending-data-files 
//Reference:https://osandnetworkingcslab.wordpress.com/client-server-chat-using-tcp/ 

КЛИЕНТ

//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(void) 
{ 
int sockfd = 0; 
int bytesReceived = 0,i=0,k=0; 
char recvBuff[256]; 
char buffer[20]; 
struct sockaddr_in serv_addr; 
memset(&serv_addr,0, sizeof(serv_addr)); 
/* Create a socket first */ 
sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if(sockfd==-1) 
{ 
    printf("\n Error in socket creation\n"); 
    exit(1); 
} 
printf("Socket created successfully\n"); 
/* Initialize sockaddr_in data structure */ 
serv_addr.sin_family = AF_INET; 
serv_addr.sin_port = htons(5000); // port 
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 

/* Attempt a connection */ 
k=connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 
if(k==-1) 
{ 
    printf("Error in connecting to server\n"); 
    exit(1); 
} 
printf("Connection established\n"); 
while(1) 
{ 
    strcpy(buffer,"end"); 
    printf("Enter command:\t"); 
    scanf("%s",buffer); 
    /*---- Send message to the socket of the incoming connection ----*/ 
    k=send(sockfd,buffer,20,0); 
      if(k==-1) 
      { 
       printf("Error in sending\n"); 
       exit(1); 
      } 
    printf("Sending command %s\n",buffer); 
    if(strncmp(buffer,"end",3)==0)//Use "end" to end communication with server 
     { 
      printf("Terminating the connection\n"); 
      break; 
     } 
    else if(strncmp(buffer,"list",4)==0) 
    { 
     /* Create file where data will be stored */ 
     FILE *fp,*fp1; 
     fp = fopen("filesdata.txt", "w"); 
     if(NULL == fp) 
     { 
      printf("Error opening file\n"); 
      return 1; 
     } 
     /* Receive data in chunks of 256 bytes */ 
     printf("Recieving reply\n"); 
     while((bytesReceived = read(sockfd, recvBuff, 256)) > 0) 
     { 
      fwrite(recvBuff, 1,bytesReceived,fp); 
     } 
     if(bytesReceived < 0) 
     { 
      printf("\n Read Error \n"); 
     } 
     fclose(fp); 
     fp1=fopen("filesdata.txt","r"); 
     if(NULL == fp1) 
     { 
      printf("Error opening file\n"); 
      return 1; 
     } 
     printf("List of files:\n"); 
     printf("\n*****************\n"); 
     while(fgets(recvBuff,256,fp1)) 
      printf("%s",recvBuff); 
     printf("\n*****************\n"); 
     fclose(fp1); 
    } 
    else 
    { 
     //Create file where data will be stored 
     FILE *fp2,*fp3; 
     fp2 = fopen("copy.txt", "w"); 
     if(NULL == fp2) 
     { 
      printf("Error opening file\n"); 
      return 1; 
     } 
     printf("Recieving reply\n"); 
     // Receive data in chunks of 256 bytes 
     while((bytesReceived = read(sockfd, recvBuff, 256)) > 0) 
     { 
      fwrite(recvBuff, 1,bytesReceived,fp2); 
     } 
     if(bytesReceived < 0) 
     { 
      printf("\n Read Error \n"); 
     } 
     fclose(fp2); 

     fp3=fopen("copy.txt","r"); 
     if(NULL == fp3) 
     { 
      printf("Error opening file\n"); 
      return 1; 
     } 
     //Contents of files or negative feedback 
     printf("\n*****************\n"); 
     while(fgets(recvBuff,256,fp3)) 
      printf("%s",recvBuff); 
     printf("\n*****************\n"); 
     fclose(fp3); 
    } 
} 
close(sockfd); 
exit(0); 
return 0; 
} 

//Reference:http://codereview.stackexchange.com/questions/43914/client-server-implementation-in-c-sending-data-files 
//Reference:https://osandnetworkingcslab.wordpress.com/client-server-chat-using-tcp/ 

Одна вещь, чтобы отметить, что, когда я прервать на стороне сервера программы данные сразу, поступивших в но я хочу, чтобы он был одновременно отправлен и получен как чат. Заранее благодарю всех за помощь!

+1

Просто заметьте: do * not * открыть файл на C, если вы собираетесь запустить системную команду, записывающую его. Система будет обрабатывать все это. Если у вас есть открытая ручка, это может даже остановить систему от возможности записи в файл из-за блокировки. –

ответ

0

Скорее всего, проблема в том, что вы постоянно читаете данные на клиенте. read() здесь блокируются до тех пор, пока данные не будут доступны, и поскольку сервер уже отправил все, что он будет висеть навсегда. Если вы убьете сервер, то read() вернется, и вы справитесь с ним должным образом.

Необходимо отправить данные в блоки с информацией о длине в начале. Тогда вы знаете, что будет дан ответ n байт и может читать байты n, а затем вернуться к запросам пользователя для команды. В противном случае вы никогда не узнаете, когда сервер завершил отправку ответа на команду.

Так что просто отправьте nread перед отправкой данных. ПРИМЕЧАНИЕ это предполагает, что переменная имеет длину 4 байта и что оба конца имеют одинаковую идентификацию. Вы должны использовать определенные размеры бит для переменных, чтобы убедиться.

if(nread > 0) 
{ 
    write(connfd, &nread, 4); 
    write(connfd, buff, nread); 
} 

Тогда в приемном конце вы первые read четыре байта в переменной, а затем прочитал, что много байт (не зацикливание до чтения, так что вы получите все из них), а не читать навсегда.


Кроме того, это очень неправильно:

FILE *fp = fopen("files.txt","w"); 
system("ls>>files.txt"); 
fclose(fp); 

Здесь вы открываете файл для записи, а затем сообщить оболочке, чтобы написать к нему, а затем закрыть его. Вы не должны открывать файл самостоятельно. В некоторых случаях это может даже заблокировать команду ls от записи в файл из-за блокировки. Вам нужна только команда system, № fopen или fclose.

+0

Большое спасибо за ответ, но я уже отправил файл в 256-байтовый пакет. Однако нет никакого выхода, как вы упомянули. Но я действительно не могу этого сделать. Пожалуйста, помогите мне с кодом. Я осознал свою ошибку в «ls >> files.txt», и я обязательно ее поменяю. – Atashi

+0

@ Аташи Нет, вы отправляете столько байтов, сколько есть в файле, а не 256 всегда, и клиент не знает сумму. Простой сеанс отладки покажет это. –

+0

Так что я должен копировать все в буфер и отправлять его? или уменьшить размер пакета? – Atashi