【问题标题】:Program stuck writing contents to the file in C程序卡住将内容写入C中的文件
【发布时间】:2021-02-16 20:49:15
【问题描述】:

我正在从客户端向服务器发送一个文件。

  • 客户端发送文件名
  • 服务器接收文件名
  • 客户端发送文件大小
  • 服务器接收文件大小
  • 客户端发送文件内容
  • 服务器接收文件内容

当我打印出我发送的文件大小时,它是我希望发送的文件的确切字节数,这很好。问题是服务器(接收)在写入新文件时似乎没有退出 while 循环。我知道这是因为最后的打印语句 printf("The server has received the requested document\n");从未到达,它只是挂起。这可能是什么原因造成的?

客户端 sn-p(发送):

 else if(strcmp(shortCommand, "put") == 0){
            
            
            char *tmp = buf + 4;
            char filename[MAX_BLOCK_SIZE];
        size_t size, bytes_read, bytes_written;
        int x;

            strcpy(filename, "filename ");
            strcat(filename, tmp);
            FILE *fp;
            printf("File name: %s\n", tmp);
            fp = fopen(tmp, "rb");
            if(fp == NULL){
                
                printf("ERROR: Requested file does not exist.\n");
                
            }
            else{
            printf("Client sending filename...\n");
            if ((x = write(sd, buf, sizeof(buf))) < 0){     //sending the file name to the client first
                printf("Error sending client's filename.\n");
            }

            printf("Client sending file...\n");
            
            fseek(fp, 0, SEEK_END);
            size = ftell(fp);
            fseek(fp, 0, SEEK_SET);
            printf("Sending file size\n");
            
            if((write(sd, &size, sizeof(size))) < 0){ //sending filesize
                printf("error sending file size\n");
            }
            
            printf("Sending file\n");
            while((bytes_read = fread(buf, 1, sizeof(buf), fp)) > 0){ //sending file contents
            
                if ((bytes_written = write(sd, buf, bytes_read)) < 0){
                    printf("Error sending client file.\n");
                }
            
            }
            printf("bytes written: %ld\n", bytes_written);
            fclose(fp);
            }   
    }

服务器 sn-p(接收):

if(strcmp(shortCommand, "put") == 0){
                char *tmp = buf + 4;
                char filename2[MAX_BLOCK_SIZE];
                size_t  filesize;
                size_t total_bytes_read = 0;
                ssize_t bytes_read = 0;
                size_t error;
                FILE *fp;
                strcpy(filename2, tmp);
                printf("Server receiving file name...\n"); //filename is received on the first read before this IF
                fp = fopen(filename2, "wb");
                if(fp == NULL){
                    printf("File could not be opened.\n");
                    exit(1);
                }
                
                printf("Server receiving file size...\n");
                
                if((error = read(sd, &filesize, sizeof(filesize))) < 0){ //receiving file size
                    perror("Error reading filesize\n");
                    exit(1);
                }
                
                printf("Filesize is: %ld \n", filesize);
                
                while(total_bytes_read < filesize){
                    while((bytes_read = read(sd, buf, sizeof(buf))) > 0){ //receving file contents and writing to file
                        fwrite(buf, 1, bytes_read, fp);
                        total_bytes_read += bytes_read;
                    if(ferror(fp)){
                        perror("error");
                        fclose(fp);
                    }
                    }
                }
                printf("The server has received the requested document.\n");
                fflush(stdout);
                fclose(fp);
    }

我强行退出程序后,其实可以看到文件已经被复制了。只是不退出那个while循环让我回到客户端。

【问题讨论】:

  • 您可以在每次循环迭代时检查 bytes_read 的值
  • 如果 read() 函数在任何时候返回 -1 或 0,你的程序可能永远不会退出这个循环 while(total_bytes_read
  • @Arthur 所以对于一个超过 6000 个字节的文件,每次迭代读取 256 个字节,直到最后一次迭代读取剩余的字节数,然后它再次挂起。 256 是我分配给 buf 的大小,例如 char buf[MAX_BLOCK_SIZE] 其中MAX_BLOCK_SIZE 是 256
  • @Arthur 但是我的 while 循环就像while((bytes_read = read(sd, buf, sizeof(buf))) &gt; 0),所以它应该在返回 0 或 -1 时停止,对吧?
  • 我在谈论另一个循环:“while(total_bytes_read

标签: c file file-transfer fwrite fread


【解决方案1】:

是时候进行一些基本的调试了。我建议将您的读取循环更改为以下内容:

while (total_bytes_read < filesize) {
    printf("DEBUG A: total=%zu, size=%zu\n", total_bytes_read, filesize);
    while ((bytes_read = read(sd, buf, sizeof(buf))) > 0) {
        printf("DEBUG B: read=%zd\n", bytes_read);
        fwrite(buf, 1, bytes_read, fp);
        total_bytes_read += bytes_read;
        printf("DEBUG C: total=%zu\n", total_bytes_read);
        if (ferror(fp))
            printf("DEBUG D\n");
            perror("error");
            fclose(fp);
        }
        printf("DEBUG E\n");
    }
    printf("DEBUG F\n");
}
printf("DEBUG G\n");

然后运行它,将输出通过less 或其他寻呼机传送,然后希望它会变得更清楚实际发生的情况。

请随意发布此修改后代码的输出(在评论中或在实际问题中),我们无疑会帮助分析。

【讨论】:

  • 这实际上很有帮助,谢谢。我不知道如何使用“少”,甚至不知道寻呼机是什么,我很抱歉。但是通过这个调试,对于'DEBUG C',我可以看到当所有字节都读入total_bytes时循环停止。所以每个字节都已正确写入。但在那之后,它就挂了
  • @DarrenFernando:所以在最后的 C 之后你有 no 更多的输出?我建议您根据我的更新添加更多内容,然后重试,然后发布您得到的输出。
  • 嘿,Pax,所以我已经想出了如何为其他想知道的人做些什么。所以我删除了最初的 while 循环 while (total_bytes_read &lt; filesize),而是在下一个 while 循环中添加了条件 if(total_bytes_read == filesize) then`break`,以便在写入所有字节后循环退出,并且它可以工作。您的调试帮助了我很多,谢谢!
猜你喜欢
  • 2012-02-19
  • 1970-01-01
  • 2015-07-20
  • 1970-01-01
  • 2017-06-21
  • 1970-01-01
  • 1970-01-01
  • 2015-08-20
  • 2011-10-07
相关资源
最近更新 更多