2013-05-12 6 views
-1

J'écris un serveur simple pour transférer un fichier au client. Voici les codes sources.Pourquoi lire et écrire ne peut pas fonctionner normalement

//server.c 
#include "general.h" 
#define LISTENQ 10 
#define BUFSIZE 1024 
#define FILENAME "List" 

void sendlist(int sockfd) { 
    int fd = open(FILENAME, O_RDONLY); 
    char readbuf[BUFSIZE]; 
    ssize_t n; 

    if(fd == -1) 
      exit(1); 

    for(;;) { 
      if((n = read(fd, readbuf, BUFSIZE)) > 0) 
        write(sockfd, readbuf, BUFSIZE); 
      else 
        break; 
    } 

    close(fd); 
    close(sockfd); 
} 

int main(int argc, char ** argv) { 
    int listenfd, connfd; 
    pid_t childpid; 
    socklen_t len; 
    struct sockaddr_in cliaddr, servaddr; 

    listenfd = socket(AF_INET, SOCK_STREAM, 0); 

    bzero(&servaddr, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(SERV_PORT); 

    bind(listenfd, (struct sockaddr_in *)&servaddr, sizeof(servaddr)); 
    listen(listenfd,LISTENQ); 

    for(;;) { 
      len = sizeof(cliaddr); 
      connfd = accept(listenfd, (struct sockaddr_in *)&cliaddr, &len); 
      if((childpid = fork()) == 0) { 
        close(listenfd); 
        sendlist(connfd); 
        exit(0); 
      } 
      close(connfd); 
    } 
} 



//client.c 
#include "general.h" 

#define MAXLINE 1024 
#define FILENAME "List2" 

void getlist(int sockfd) { 
    int fd = creat(FILENAME, S_IRUSR | S_IWUSR); 
    char buf[MAXLINE]; 
    ssize_t n; 

    if(fd == -1) 
      exit(2); 

    for(;;) { 
      if((n = read(sockfd, buf, MAXLINE)) > 0) 
        write(fd, buf, MAXLINE); 
      else 
        break; 
    } 

    close(fd); 
} 

int main(int argc, char ** argv) { 
    int sockfd; 
    struct sockaddr_in servaddr; 

    if(argc != 2) 
      exit(1); 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    bzero(&servaddr, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_port = htons(SERV_PORT); 
    inet_pton(AF_INET, argv[1], &servaddr.sin_addr); 

    connect(sockfd, (struct sockaddr_in *)&servaddr, sizeof(servaddr)); 

    getlist(sockfd); 

    exit(0); 
} 

Mon problème est le suivant: le fichier List et List2 ne sont pas identiques. Par exemple, le contenu de la liste des fichiers est: test Contenu du fichier List2 contient non seulement test, mais aussi de nombreux codes illisibles comme ceci:

^@^@^@^@^@^@^@^@^@<8c>]úUü^?^@^@ ^G^\Vü^?^@^@^A^@^@^ 

Je pense que la raison sont fonction de lecture et écriture. Ne devrais-je pas les utiliser? Merci

+0

En savoir plus sur [sondage (2)] (http://man7.org/linu x/man-pages/man2/poll.2.html) et recherche le 'problème C10K' –

Répondre

4

Vous écrivez la totalité de la mémoire tampon dans un fichier, alors que seuls les premiers n octets sont valides. Remplacer:

for(;;) { 
     if((n = read(sockfd, buf, MAXLINE)) > 0) 
       write(fd, buf, MAXLINE); 

Avec:

for(;;) { 
     if((n = read(sockfd, buf, MAXLINE)) > 0) 
       write(fd, buf, n); 

Et toutes les occurrences similaires en conséquence.

+0

Jusqu'à la seconde. –

+0

Quoi? Je ne comprends pas ... –

+1

Nous avons répondu à la même seconde. –

0

Lecture() et écriture() peut faire partiel lit/écrit. Ceci est indiqué par leur valeur de retour qui est le nombre d'octets transmis avec succès, qui peut être différent du 3ème argument qui leur a été donné.

while(1) { 
    int n; 
    unsigned todo, done; 
    n = read(fd, readbuf, BUFSIZE); 
    if (n <= 0) break; 

    for(todo=n,done=0; done < todo; done += n) { 
     n = write(sockfd, readbuf+done, todo - done); 
     if (n <= 0) return FAILURE; 
     } 
    } 
1
  1. Je crois que vous devez Memset les tampons premiers
  2. envoyer uniquement ce que vous lisez en fait pas tout ce que vous avez
  3. écrire seulement ce que vous avez reçu pas la taille de la mémoire tampon

comme

for(;;) { 
    memset(readbuf , 0, BUFSIZE); // Clear Memory here 
    if((n = read(fd, readbuf, BUFSIZE)) > 0) 
       write(sockfd, readbuf, n); // Send what you read 
     else 
       break; 
} 



// similarly While reading 
for(;;) { 

     memset(buf , 0 , MAXLINE); // again do a memset 

     if((n = read(sockfd, buf, MAXLINE)) > 0) 
       write(fd, buf, n); // Write What you read 
     else 
       break; 
} 
+0

Le memset n'est pas nécessaire. Vous avez juste besoin de vous souvenir de ce que vous devriez envoyer et de ce que vous ne devriez pas envoyer. Envoyer beaucoup de zéro octets est tout aussi mauvais que d'envoyer des ordures aléatoires. – wildplasser

Questions connexes