【问题标题】:How to send a size_t variable with a TCP socket in C?如何在 C 中使用 TCP 套接字发送 size_t 变量?
【发布时间】:2018-05-07 16:42:26
【问题描述】:

我正在处理将数据发送到 TCP 服务器的东西,但首先它应该以 8 个字节发送数据的大小。

也就是说,服务器将读取发送给它的前 8 个字节并将它们转换回 size_t 变量。我的问题是,当文件大小不使用任何最高位(即 83 = 0000000S

这就是我的做法:

void send_file_to_server(char *filename){

    struct stat buf;
    if (stat(filename, &buf)==-1){ exit(1); }
    size_t file_size = buf.st_size;

    char *filesize_string = calloc(1, 8);
    filesize_string = (char*)&file_size;

    //this function actually writes to the server
    write_to_server((char*) filesize_string);


   // will be code later on that sends the actual file using write_to_server()

}

传递给我的 write_to_server() 函数的 char* 有一些奇怪的行为:它只将其识别为大小为 6 的字符串,并且在传入之前就被扭曲了。感谢任何有关如何使这项工作的建议.

注意:我不必担心字节顺序(htonl 等)或 size_t 的不同大小,因为这适用于只能在特定 VM 上运行的项目。

编辑:

这是另一个函数:

void write_to_server(char *message){
    ssize_t bytes_sent = 0;
    ssize_t message_size = strlen(message);

    while ( bytes_sent < message_size ){
        ssize_t ret = write(server_socket, message+bytes_sent, message_size-bytes_sent);
        if (ret==0){
            print_connection_closed(); 
            exit(1);
        }
        if (ret==-1 && (errno!=EINTR || errno!=EAGAIN)){
            printf("write failed: sent %zd bytes out of %zd\n", bytes_sent, message_size);
            exit(1);
        }
        if (ret!=-1){ bytes_sent+=ret; }
    }   
}

【问题讨论】:

  • 我的问题是,当文件大小不使用任何最高位时 - 所以这是一个错误的逻辑。使用正确的发送所有数据的方法。零有意义的..
  • calloc 调用的目的是什么?它似乎所做的只是泄漏内存。
  • 您将filesize_string 变量的地址传递给write_to_server 函数。我怀疑你真的想传递file_size 变量的地址,或者filesize_string 变量的值。
  • 你应该好好利用sizeof(size_t)而不是将其硬编码为8
  • @Ian Abbott 它是为了获取已经设置为 0 的内存。所以字符串的高字节已经是 0。是的,我想我没有显示它是免费的。

标签: c sockets tcp network-programming


【解决方案1】:

您不能使用strlen() 来确定二进制数据的长度。一旦在长度字段的二进制编码中看到零 (NUL) 字节,它就会对数据进行错误计数。

编写一个更“原始”的函数,将数据的地址作为参数,例如

void write_to_server_raw(const void *message, size_t message_size) {
    ...
}

如果您仍然需要发送 NUL 终止字符串的能力,您可以重写现有的 write_to_server() 函数,以便它调用新函数来完成真正的工作。

void write_to_server_string(const char *message) {
    size_t message_size = strlen(message);
    write_to_server_raw(message, message_size);
}

【讨论】:

  • 哦,哇,我真笨!非常感谢,一定要试试这个。
  • 嗯,我希望size_t message_size = strlen(message) + 1;
  • @chux 取决于二进制编码是否必须包含 NUL 字节。 OP的原始代码没有。我怀疑实际上 OP 实际上并不想使用 _string 方法,因为他们正在构建一个协议来传输可能包含原始二进制数据的任意文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 1970-01-01
  • 2012-09-23
  • 1970-01-01
相关资源
最近更新 更多