客户端读取另一个文件后没有读取任何数据

标签 c linux sockets pthreads

我正在编写一个简单的客户端/服务器应用程序,但遇到了一个非常奇怪的问题。

我正在尝试向客户端发送一个 .zip 文件,然后再发送一些数据。 发送 .zip 工作正常,服务器写入套接字,客户端从套接字读取,正如预期的那样。

问题紧随其后。 服务器运行良好并不断写入套接字,但客户端不会读取任何内容。无论我尝试发送什么,它都会卡在下一个 read() 调用上。

我已经检查过套接字描述符是否正常,确实如此。我也想过可能是socket里面的数据不够client读取,但是肯定是有的。

我还尝试在发送该 .zip 文件之前和之后执行相同的写入/读取操作:之前它工作正常,但客户端在发送该文件之后看不到它。压缩。 我没主意了。

这是我用来发送 .zip 的函数:

typedef struct thData{
int idThread; //thread ID
int cl; //client descriptor
}thData;

void send_info(struct thData tdL)
{
    char file_path[256]="v1.zip";
    char sd_buffer[256];
    bzero(sd_buffer, 256); 

    FILE *fd = fopen(file_path, "rb");
    if(fd == NULL)
    {
        printf("ERROR: %s not found.\n", file_path);
        exit(1);
    }


    int read_size;
    int write_size;
    while((read_size = fread(sd_buffer, sizeof(char), 256, fd)) > 0)
    {
        if((write_size=write(tdL.cl, sd_buffer, read_size)) < 0)
        {
            perror("ERROR: writing to client: \n");
            break;
        }
        bzero(sd_buffer, 256);
    }
} 

以及我用来接收 .zip 的内容:

void receive_info(int sd) //sd being the socket descriptor
{
    char* file_path = "subject.zip";
    char received_buffer[256];

    int total_received=0;
    int total_wrote=0;

    FILE *fd = fopen(file_path, "wb");
    if(fd == NULL)
        printf("Cannot open %s\n", file_path);
    else
    {
        bzero(received_buffer, 256); 
        int read_size = 0;
        while((read_size = read(sd, received_buffer, 256)) > 0) 
        {
            total_received=total_received+read_size;

            int write_size = fwrite(received_buffer, sizeof(char), read_size, fd);
            total_wrote=total_wrote+read_size;

            if(write_size < read_size)
            {
                perror("ERROR: \n");
            }
            bzero(received_buffer, 256);
            if (read_size == 0 || read_size != 256) 
            {
                break;
            }
        }
        if(read_size < 0)
        {

          perror("ERROR: reading: ");
          exit(1);

        }
        fclose(fd); 
    }
}

如有任何帮助,我们将不胜感激。

最佳答案

我认为问题是你读得太多了。

在 TCP 中,从一个点发送到另一个点的数据包没有边界。它只是一个字节流,从 recv/read() 接收的片段与从 send/write() 发送的片段没有关系(原则上)。

现在,假设您的 ZIP 文件有 300 个字节长,而您的额外数据有 10 个字节长。您的发件人代码将执行以下操作:

  • 写入 256 个字节(ZIP 中的第一部分)。
  • 写 44 个字节(ZIP 的最后一段)。
  • 写入 10 个字节(额外数据)。

您的接收器代码将执行以下操作:

  • 读取 256,得到 256 个字节(ZIP 中的第一部分)。
  • 读取 256,得到 54 个字节(ZIP 的最后一段加上额外数据)。
  • 读取XXX字节,永远等待!

如果仔细查看 ZIP 文件,您可能会在 subject.zip 的末尾看到那些额外的字节。

如果您不想关闭并打开另一个套接字,解决方案是使协议(protocol)更复杂一些。例如,您可以在包含文件大小的文件(标题)之前发送一个结构。这样接收方就会知道何时停止阅读。

PS:请注意,您的代码存在一些风险。例如,write() 可能不会写入所有给定的字节,但您没有检查它;你没有关闭文件...

PS2:我很好奇你觉得需要写 sizeof(char) 而不是 1 但是你写 256 而不是sizeof(sd_buffer)

关于客户端读取另一个文件后没有读取任何数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34842604/

相关文章:

c - omp parallel 用于输出顺序

c - 使用pthread执行矩阵乘法

linux - Bash 脚本执行多个命令

调用外部程序时 php exec() 返回错误(postmap)

c++ - 指针和缓存利用率

objective-c - Objective C 语法错误

c - 你将使用什么排序技术?

objective-c - IOS中的套接字断开

java - Apache HTTPD 关闭连接或不将请求重定向到 servlet 容器

android - MulticastSocket保持监听功能