2015-01-17 4 views
1

У меня есть client.c и server.c, я пытаюсь отправить файл с клиента на сервер и с сервера на клиент ... Файл получен сервер, но когда сервер отправляет файл, клиент останавливается или не получает файл, функция SendFile():Отправка файла (от клиента к серверу и от сервера к клиенту)

void sendfile(int fd,char* filename) 
{ 
    char buff[0x1000]; 
    FILE *file = fopen(filename, "rb"); 
    if (!file) 
    { 
     printf("Can't open file for reading"); 
     return; 
    } 
    while (!feof(file)) 
    { 
     int rval = fread(buff, 1, sizeof(buff), file); 
     if (rval < 1) 
     { 
      printf("Can't read from file\n"); 
      fclose(file); 
      return; 
     } 

     int off = 0; 
     do 
     { 
      int sent = send(fd, &buff[off], rval - off, 0); 
      printf("Sending ...\n"); 
      if (sent < 1) 
      { 
       printf("Can't write to socket"); 
       fclose(file); 
       return; 
      } 
      printf("[SendFile]Fisierul a fost trimis!\n"); 
      off += sent; 
     } 
     while (off < rval); 
    } 
fclose(file); 
} 

GetFile():

void getFile(int fd,char* filename) 
{ 
    int rval; 
    char buff[0x1000]; 
    FILE *file = fopen(filename, "w+"); 
    if (!file) 
    { 
     printf("Can't open file for writing"); 
     return; 
    } 

    do 
    { 
     rval = recv(fd, buff, sizeof(buff), 0); 
     if (rval < 0) 
     { 
      printf("Can't read from socket"); 
      fclose(file); 
      return; 
     } 

     if (rval == 0) 
      break; 

     int off = 0; 
     do 
     { 
      int written = fwrite(&buff[off], 1, rval - off, file); 
     printf("[server]Writing %d bytes\n",written); 
      if (written < 1) 
      { 
       printf("Can't write to file"); 
       fclose(file); 
       return; 
      } 

      off += written; 
     } 
     while (off < rval); 
    printf("[server]File received!\n"); 
    } 
    while(1); 
    fclose(file); 
} 

клиент основной ():

int main (int argc, char *argv[]) 
{ 
    int sd; 
    struct sockaddr_in server; 

    if (argc != 2) 
    { 
     printf ("[client] Sintaxa: %s <filename>\n", argv[0]); 
     return -1; 
    } 

    if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1) 
    { 
     perror ("[client] Eroare la socket().\n"); 
     return errno; 
    } 

    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    server.sin_port = htons (port); 

    if (connect (sd, (struct sockaddr *) &server,sizeof (struct sockaddr)) == -1) 
    { 
     perror ("[client]Eroare la connect().\n"); 
     return errno; 
    } 
    sendfile(sd,"test.cpp"); 
    printf("File sent\n"); 
    getFile(sd,"server.c"); 
    close (sd); 
} 

Петля из server.c

while (1) 
    { 
     int client; 
     int length = sizeof (from); 

     printf ("[server]Asteptam la portul %d...\n",port); 
     fflush (stdout); 

     client = accept (sd, (struct sockaddr *) &from, &length); 

     if (client < 0) 
     { 
     perror ("[server]Eroare la accept().\n"); 
     continue; 
     } 

    if((pid=fork()) == 0) 
    { 

    getFile(client,"test.cpp"); 
     sendfile(client,"server.c"); 
     printf("File sent\n"); 
    close(client); 
    } 

} 
+1

Не делать 'в то время как (! Feof (...))', так как это будет почти во всех случаях не работает, как вы ожидаете. Причина в том, что флаг конца файла не установлен до * после *, который вы пытаетесь прочитать из-за файла, что означает, что такой цикл будет повторяться слишком много. Вместо этого, например, 'while ((res = fread (...))> 0)' –

+1

Также вы можете прочитать о системном вызове Linux ['sendfile'] (http://man7.org/linux/man-pages/ man2/sendfile.2.html). –

+0

Где именно программа зависает?До этого какой-либо из вызовов сигнализирует об ошибке? Какая ошибка это сигнализирует? Что делать, если вы удалите код fork() и просто напишите два отдельных исполняемых файла? –

ответ

2

начать с.

  1. принимают(), подключение(), RECV() .. все блокируют звонки так что в теории ваша программа может быть заблокирован в любой точке этих вызовов до тех пор, пока использовать не блокирующие сокеты. Из программы она выглядит, как вы используете блокирующие сокеты

  2. Я хотел бы предложить вам прочитать хороший сокет программирование учебник как этого первого http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html

Во-вторых

Я хотел бы предложить вам иметь инструмент, подобный wirehark или любой другой инструмент анализатора пакетов, запускающий для отладки вашей проблемы.

Наконец вы можете сделать что-то вроде следующих фрагментов кода попробовать

  1. Установить сокеты в режим без блокировки с помощью вызова API fnctl.

    int rc = fcntl(newFd, F_GETFL,0); 
    rc |= O_NONBLOCK; 
    rc = fcntl(newFd, F_SETFL,rc); 
    
  2. Опрос сокет для событий Вы можете использовать что-то вроде выбора, опрос для
    же. Вот хороший пример для выбора в учебнике Beej. http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#selectman

  3. ошибки ручки правильно. Неблокирующие сокеты могут возвращать ошибку EAGAIN или EWOULDBLOCK, которая должна обрабатываться правильно. Ошибка означает, что сокет не читается или записывается в настоящий момент для поиска событий и повторите попытку. Состязание на линии.

    rval = recv(fd, buff, sizeof(buff), 0); 
        if (rval < 0) 
        { 
         if((errno == EWOULDBLOCK)||(errno ==EAGAIN)) 
         { 
          continue; 
         } 
         else 
          //cleanup 
        } 
    
0

проблема Тре была do { ... } while(1); от GetFile ... так что я удалил петлю ...

Смежные вопросы