2013-05-07 1 views
0

Прежде всего, я хотел бы указать, что я не очень хороший программист, поэтому, пожалуйста, будьте терпеливы со мной. Логика в программе следующая: клиент отправляет серверу текстовый файл, сервер сохраняет его под другим именем. Короче говоря, очень похожа на эту тему: «File transfer server/client using socket», за исключением того, что я использую другой протокол. Я думаю, что мне удалось успешно отправить файл, но похоже, что сервер, после чего создается пустой файл, застревает в цикле/ничего не пишет в нем.Передача текстового файла клиент-сервер с использованием UDP и сокетов на C++, сервер создает пустой файл

Вот код клиента:

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> /* memset() */ 
#include <sys/time.h> /* select() */ 
#include <errno.h> 
#include <sys/stat.h> 
#include <fcntl.h> 


#define REMOTE_SERVER_PORT 1500 
#define MAX_MSG 100 
#define PLIK "/home/aatami/Documents/programowanie/serwer/plik.txt" 
#define LENGTH 512 
int main(int argc, char *argv[]) { 

    int sd, rc, i,fd; 
    unsigned int cliLen; 
    struct sockaddr_in cliAddr, remoteServAddr; 
    struct hostent *h; 
    char buf[LENGTH]; 
    /* check command line args */ 
    if(argc<3) { 
    printf("usage : %s <server> <data1> ... <dataN> \n", argv[0]); 
    exit(1); 
    } 

    /* get server IP address (no check if input is IP address or DNS name */ 
    h = gethostbyname(argv[1]); 
    if(h==NULL) { 
    printf("%s: unknown host '%s' \n", argv[0], argv[1]); 
    exit(1); 
    } 

    printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name, 
    inet_ntoa(*(struct in_addr *)h->h_addr_list[0])); 

    remoteServAddr.sin_family = h->h_addrtype; 
    memcpy((char *) &remoteServAddr.sin_addr.s_addr, 
    h->h_addr_list[0], h->h_length); 
    remoteServAddr.sin_port = htons(REMOTE_SERVER_PORT); 

    /* socket creation */ 
    sd = socket(AF_INET,SOCK_DGRAM,0); /* port 0 - system gets the first free one */ 
    if(sd<0) { 
    printf("%s: cannot open socket \n",argv[0]); 
    exit(1); 
    } 

    /* bind any port */ 
    cliAddr.sin_family = AF_INET; 
    cliAddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    cliAddr.sin_port = htons(0); 

    rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr)); 
    if(rc<0) { 
    printf("%s: cannot bind port\n", argv[0]); 
    exit(1); 
    } 


    /* send data */ 
    for(i=2;i<argc;i++) { 
    rc = sendto(sd, argv[i], strlen(argv[i])+1, 0, 
     (struct sockaddr *) &remoteServAddr, 
     sizeof(remoteServAddr)); 

    if(rc<0) { 
     printf("%s: cannot send data %d \n",argv[0],i-1); 
     close(sd); 
     exit(1); 
    } 
    /* send text file */ 


     char sdbuf[LENGTH]; 
     printf("[Client] Sending %s to the Server... ", PLIK); 
     FILE *fs = fopen(PLIK, "r"); 
     if(fs == NULL) 
     { 
      printf("ERROR: File %s not found.\n", PLIK); 
      exit(1); 
     } 

     bzero(sdbuf, LENGTH); 
     int fs_block_sz; 
     while((fs_block_sz = fread(sdbuf, sizeof(char), LENGTH, fs)) > 0) 
     { 
      if(send(sd, sdbuf, fs_block_sz, 0) < 0) 
      { 
       fprintf(stderr, "ERROR: Failed to send file %s. (errno = %d)\n", PLIK,   errno); 
       break; 
      } 
      bzero(sdbuf, LENGTH); 
     } 
     printf("Ok File %s from Client was Sent!\n", PLIK); 


    } 

    return 1; 

} 

И код сервера:

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> /* close() */ 
#include <string.h> /* memset() */ 
#include <errno.h> 
#define LENGTH 512 
#define LOCAL_SERVER_PORT 1500 
#define MAX_MSG 100 
#define PLIKSERV "/home/aatami/Documents/programowanie/serwer/plikserv.txt" 
int main(int argc, char *argv[]) { /* licznik argumentow, tablica argumentow */ 

    int sd, rc,nsockfd; 
    unsigned int n,cliLen; 
    struct sockaddr_in cliAddr, servAddr; 
    char msg[MAX_MSG]; 
    char buf[512],sbuf[LENGTH]; 
    /* socket creation */ 
    sd=socket(AF_INET, SOCK_DGRAM, 0); 
    if(sd<0) { 
    printf("%s: cannot open socket \n",argv[0]); 
    exit(1); 
    } 

    /* bind local server port */ 
    servAddr.sin_family = AF_INET; 
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servAddr.sin_port = htons(LOCAL_SERVER_PORT); 
    rc = bind (sd, (struct sockaddr *) &servAddr,sizeof(servAddr)); 
    if(rc<0) { 
    printf("%s: cannot bind port number %d \n", 
     argv[0], LOCAL_SERVER_PORT); 
    exit(1); 
    } 

    printf("%s: waiting for data on port UDP %u\n", 
     argv[0],LOCAL_SERVER_PORT); 



    /* server infinite loop */ 
    while(1) { 

    /* init buffer */ 
    memset(msg,0x0,MAX_MSG); 


    /* receive message */ 
    cliLen = sizeof(cliAddr); 
    n = recvfrom(sd, msg, MAX_MSG, 0, 
     (struct sockaddr *) &cliAddr, &cliLen); 

    if(n<0) { 
     printf("%s: cannot receive data \n",argv[0]); 
     continue; 
    } 

    /* print received message */ 
    printf("%s: from %s:UDP%u : %s \n", 
     argv[0],inet_ntoa(cliAddr.sin_addr), 
     ntohs(cliAddr.sin_port),msg); 

     unsigned int sin_size = sizeof(struct sockaddr_in); 




     FILE *fr = fopen(PLIKSERV, "a"); 
     if(fr == NULL) 
      printf("File %s Cannot be opened file on server.\n", PLIKSERV); 
     else 
     { 
      bzero(sbuf, LENGTH); 
      int fr_block_sz = 0; 
      while((fr_block_sz = recvfrom(sd, buf, LENGTH, 0,(struct sockaddr *) &cliAddr, &cliLen)) > 0) 
      { 
       int write_sz = fwrite(buf, sizeof(char), fr_block_sz, fr); 
       if(write_sz < fr_block_sz) 
       { 
        perror("File write failed on server.\n"); 
       } 
       bzero(buf, LENGTH); 
       if (fr_block_sz == 0 || fr_block_sz != 512) 
       { 
        break; 
       } 
      } 
      if(fr_block_sz < 0) 
      { 
       if (errno == EAGAIN) 
       { 
        printf("recv() timed out.\n"); 
       } 
       else 
       { 
        fprintf(stderr, "recv() failed due to errno = %d\n", errno); 
        exit(1); 
        } 
       } 
      printf("Ok received from client!\n"); 
      fclose(fr); 
     } 

    }/* end of server infinite loop */ 

return 0; 

} 

Любая помощь очень ценится!

+0

Одна вещь, которую я вижу, это то, что в 'recvfrom' вы читаете в' sbuf', но в 'fwrite' вы пишете с' buf'. – Duck

+0

Я изменил его на buf во всех случаях, но результат все тот же. – Aatami

ответ

0

После просмотра вашего кода я предлагаю попробовать отправить «Hello world \ n» от клиента к серверу, посмотрите, есть ли у вас его. После того, как вы установили соединение между клиентом и сервером, попробуйте расширить код для передачи файла.

Но имейте это в виду о UDP:

«UDP использует простую модель передачи с минимальным механизмом протокола Он не имеет рукопожатия диалоги, и тем самым подвергает любую ненадежность основного сетевого протокола программы пользователя. Поскольку обычно это IP-адрес на ненадежных носителях, нет гарантии доставки, заказа или дублирования защиты. Если на уровне сетевого интерфейса необходимы средства исправления ошибок, приложение может использовать протокол управления передачей (TCP), который предназначен для этого цель."

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

+0

На самом деле, я уже переписал его с помощью TCP, и теперь я просто упрям, чтобы писать его с помощью UDP. Здесь есть способ проверить, что что-то уже реализовано - сервер получает сообщение от клиента, которое распечатывается в терминале, и оно работает просто отлично. Если я попытаюсь отправить снова и снова (сообщение и файл), окончательный текстовый файл будет поврежден - вместо того, чтобы быть пустым, он имеет несколько 1 и 0 и /. Это из-за дублирования/разложения/etc пакетов? – Aatami

+0

Боюсь, что так оно и есть. Может быть 10 случаев, когда передача прекрасна, а иногда нет, это происходит из-за дублирования/разупорядочения/отсутствия пакетов; UDP не был разработан для этой цели. В любом случае, вы UDP или TCP, вам нужно создать протокол, что указывает на то, что вы собираетесь получать. –

+0

Как это сделать для UDP? Является ли это чем-то возможным для начинающего программиста, или мне лучше оставить передачу с помощью TCP? Большое спасибо за ваш совет! – Aatami

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

  • Нет связанных вопросов^_^