c++ - 使用 C/C++ (GCC/G++) 在 Linux 中的套接字编程中发送和接收文件

标签 c++ c linux sockets network-programming

我想使用能够发送和接收文件的套接字和 C/C++ 语言来实现在 Linux 上运行的客户端-服务器架构。是否有任何图书馆可以使这项任务变得容易?谁能举个例子?

最佳答案

最便携的解决方案就是以 block 的形式读取文件,然后在循环中将数据写入套接字(同样,在接收文件时反过来)。您分配一个缓冲区,read进入该缓冲区,然后 write从该缓冲区到您的套接字(您也可以使用 sendrecv,它们是特定于套接字的写入和读取数据的方式)。大纲看起来像这样:

while (1) {
    // Read data into buffer.  We may not have enough to fill up buffer, so we
    // store how many bytes were actually read in bytes_read.
    int bytes_read = read(input_file, buffer, sizeof(buffer));
    if (bytes_read == 0) // We're done reading from the file
        break;
    
    if (bytes_read < 0) {
        // handle errors
    }
    
    // You need a loop for the write, because not all of the data may be written
    // in one call; write will return how many bytes were written. p keeps
    // track of where in the buffer we are, while we decrement bytes_read
    // to keep track of how many bytes are left to write.
    void *p = buffer;
    while (bytes_read > 0) {
        int bytes_written = write(output_socket, p, bytes_read);
        if (bytes_written <= 0) {
            // handle errors
        }
        bytes_read -= bytes_written;
        p += bytes_written;
    }
}

请务必仔细阅读 readwrite 的文档,尤其是在处理错误时。一些错误代码意味着您应该再试一次,例如使用 continue 语句再次循环,而其他错误代码则表示某些内容已损坏,您需要停止。

为了将文件发送到套接字,有一个系统调用,sendfile这正是你想要的。它告诉内核将一个文件从一个文件描述符发送到另一个,然后内核可以处理其余的事情。需要注意的是源文件描述符必须支持 mmap (如,是一个实际的文件,而不是一个套接字),并且目标必须是一个套接字(所以你不能用它来复制文件,或直接从一个套接字发送数据到另一个);它旨在支持您描述的将文件发送到套接字的用法。但是,它对接收文件没有帮助;你需要自己做这个循环。我无法告诉你为什么有一个 sendfile 调用但没有类似的 recvfile

注意 sendfile 是特定于 Linux 的;它不能移植到其他系统。其他系统通常有自己的 sendfile 版本,但确切的接口(interface)可能会有所不同(FreeBSDMac OS XSolaris)。

在 Linux 2.6.17 中,splice系统调用是 introduced ,并且截至 2.6.23 为 used internally to implement sendfile . splice 是一个比 sendfile 更通用的 API。 splicetee 的详细说明,请参阅相当不错的 explanation from Linus himself .他指出使用 splice 基本上就像上面的循环一样,使用 readwrite,只是缓冲区在内核中,所以数据不必在内核和用户空间之间传输,甚至可能永远不会通过 CPU(称为“零拷贝 I/O”)。

关于c++ - 使用 C/C++ (GCC/G++) 在 Linux 中的套接字编程中发送和接收文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2014033/

相关文章:

c++ - std::async on 成员字段的成员函数

从头文件内部引用类的实现时,c++模板类错误

linux - 我如何知道Electron需要运行哪些Debian库?

c - 无法构建 zpipe.c(Zlib 示例程序)

c++ - 指针列表初始化和释放内存

c++将NTP服务器返回的时间转换为字符串

c - C 中清除缓冲区的问题

c - 摆脱正则表达式编译器警告而不使用 "#include <regex.h>"

c - 空括号中的星号是什么意思?

未在文本文件中捕获段错误标准输出重定向时的 C 程序