【问题标题】:Transfer files with sockets使用套接字传输文件
【发布时间】:2014-05-01 02:44:11
【问题描述】:

我正在尝试使用 C 中的套接字传输文件(在本例中为 .jpg 文件)。我有我的客户端和服务器代码,但我不知道为什么传输文件的字节数比原始文件多文件。代码如下:

服务器

/***************************************************
*
*       Starting to send data file
*
***************************************************/

// Read the size of the file
recv(client.fd_client, &file.size_file, sizeof(int), 0);
recv(client.fd_client, &file.size_string, sizeof(int), 0);
recv(client.fd_client, &file.name_of_file, file.size_string, 0);
printf("Size of the file: %.3f kB\n", file.size_file/1000.);
printf("Receiving the file \"%s\"...\n", file.name_of_file);

if((file.fd_file = creat(file.name_of_file, S_IRWXU)) < 0) {
    error("Can't open the file: ");
}

while(1) {
    bzero(buffer, SIZE_BUF);
    if((numb_bytes = read(client.fd_client, buffer, SIZE_BUF)) < 0) {
        error("Can't read the file.");
    }
    write(file.fd_file, buffer, numb_bytes);
    received += numb_bytes;
    printf("Received: %.3fkB (%.3f/%.3f) kB\n", numb_bytes/1000., recibed/1000., file.size_file/1000.);
    if(numb_bytes == 0)
        break;
}

printf("Recibidos %.3f/%.3f kB\n", recibed/1000., file.size_file/1000.);

客户

/***************************************************
*
*       Starting to send data file
*
***************************************************/

// Use strncpy!
strcpy(file.name_of_file, argv[3]);
file.fd_file = open(file.name_of_file, 0); 
fstat(file.fd_file, &stat_file);
file.size_file = (unsigned int) stat_file.st_size;
file.size_string = (unsigned int) strlen(file.name_of_file) + 1;
printf("Size of the file: %.3f kB.\n", file.size_file/1000.);
printf("Sending the file \"%s\"...\n", file.name_of_file);

// Send data file
write(conection.sockfd, &file.size_file, sizeof(file.size_file));
write(conection.sockfd, &file.size_string, sizeof(file.size_string));
write(conection.sockfd, &file.name_of_file, sizeof(file.name_of_file));

while(1) {
    sended += sendfile(conection.sockfd, file.fd_file, NULL, SIZE_BUF);
    printf("send: %d\n", sended);
    printf("num_bytes: %d\n", num_bytes);
    if(sended == file.size_file)
        break;
}

printf("Sended %.3f/%.3f kB\n", sended/1000., file.size_file/1000.);

我有几个问题:

  1. 大小和文件名的传输正确发生。我不明白为什么当我使用 ntohl 时它会给我垃圾。如果我是对的,由于 Little Endian 和 Big Endian,ntohl 和 ntos 都在使用套接字传输号码之前使用。那为什么会这样呢?
  2. 文件传输也正确发生,但客户端传输或服务器接收到的字节多于原始文件大小。我尝试传输图像,但无法打开。所以我尝试使用客户端的源代码,它可以很好地到达服务器(与以前一样有更多字节),但是当我打开它时,顶部有垃圾,然后是源代码。我认为传输发生得很好,但到达的字节比需要的多。谁能告诉我为什么会这样?
  3. 我正在以 1024kB 块传输文件,因为当我尝试通过一次调用发送整个文件时,我永远无法发送所有文件。我在互联网上看到了一些例子,他们修复了某种偏移量,直到它转移并从这一点开始再次转移。这是必要的吗?起初我认为它不是,因为我不使用它并且文件到达“好”,就像它自动知道从哪里继续读取文件一样。

【问题讨论】:

    标签: c sockets file-transfer


    【解决方案1】:

    您正在发送整个名称缓冲区:

    write(conection.sockfd, &file.name_of_file, sizeof(file.name_of_file));
    

    但只读取前一个字段发送的长度:

    recv(client.fd_client, &file.size_string, sizeof(int), 0);
    recv(client.fd_client, &file.name_of_file, file.size_string, 0);
    

    缓冲区大小和字符串长度之间的差异很可能是附加文件长度的差异。你可以通过改变这个来解决这个问题:

    write(conection.sockfd, &file.name_of_file, sizeof(file.name_of_file));
    

    对此,在您的客户端代码中:

    write(conection.sockfd, &file.name_of_file, file.size_string);
    

    我将查看其他子问题,但这是您的文件大小错误的主要原因。我无法对您使用htonlntohl 的正确性做出有根据的决定,因为您没有包含转换这些字段的代码。这可能是个问题。您可以在所有时间保持结构中的原生大小,并将它们读入临时变量,然后通过在接收端通过ntohl 发送所述变量分配结果,然后发送发送方的临时变量(在他们通过htonl 收到翻译后)。

    【讨论】:

    • 我对该代码的问题不在于文件名、文件大小或文件名大小(我在控制台中打印,它们三个都可以)。问题是当我开始发送文件时。比如文件有23,415kB,但是当服务器收到它时,文件是24,427kB,我不知道为什么,因为客户端发送的正好是23,415kB。
    • 我不同意。您对“那个”代码的问题非常多是文件名(至少它本身就是一个 公然 问题)。您正在为文件名发送sizeof(file.name_of_file) 字节,但在读取端仅读取file.size_string 字节。在你说错之前,尝试一下
    • 是的!你是对的!我将sizeof(file.name_of_file) 更改为strlen(file.name_of_file) + 1,它工作正常。现在我认为服务器收到的额外字节来自变量file.name_of_file的大小,可能是?
    • 想想建议修复之前和之后代码中字节流中的内容。另外,我强烈建议您的“协议”(无论您是否知道,这就是您在这里滚动的内容)包括单个字段的 total 大小 prior包括一切的尺寸。鉴于此,您可以可靠地删除那个,并在开始拆散之前知道您拥有一切
    • 您是否建议我必须先发送 名称长度 + 名称 + 文件大小 + 文件 然后只保存最终大小(即, 数字 23,???kB 在这种情况下) 或缓冲区中的字节流?如果我必须将所有字节保存在缓冲区中,我是否必须将其拆分并将每个字段分配给相应的变量?
    猜你喜欢
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多