为什么读写无法正常工作

时间:2013-05-12 14:05:50

标签: c linux sockets

我编写了一个简单的服务器来将文件传输到客户端。以下是源代码。

//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);
}

我的问题是:文件List和List2不一样。 例如,文件列表的内容为:test 文件List2的内容不仅包含test,还包含许多不可读的代码:

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

我认为原因是读写功能。我不应该使用它们吗? 感谢

3 个答案:

答案 0 :(得分:4)

您正在将整个缓冲区写入文件,而只有第一个n字节有效。替换:

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

使用:

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

所有相似的事件都相应地发生。

答案 1 :(得分:1)

  1. 我相信你需要先设置缓冲区
  2. 仅发送您实际读取的内容而非发送的所有内容
  3. 仅写入您收到的不是缓冲区大小
  4. 喜欢

     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;
    }
    

答案 2 :(得分:0)

Read()和write()可以执行部分读/写。这由返回值表示,它是成功传输的字节数,可以与给予它们的第3个参数不同。

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;
        }
    }