使用 C/C++ (GCC/G++) 在 Linux 中的套接字编程中发送和接收文件 [英] Send and Receive a file in socket programming in Linux with C/C++ (GCC/G++)

查看:23
本文介绍了使用 C/C++ (GCC/G++) 在 Linux 中的套接字编程中发送和接收文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用能够发送和接收文件的套接字和 C/C++ 语言来实现在 Linux 上运行的客户端-服务器架构.是否有任何库可以简化此任务?谁能提供一个例子?

I would like to implement a client-server architecture running on Linux using sockets and C/C++ language that is capable of sending and receiving files. Is there any library that makes this task easy? Could anyone please provide an example?

推荐答案

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

The most portable solution is just to read the file in chunks, and then write the data out to the socket, in a loop (and likewise, the other way around when receiving the file). You allocate a buffer, read into that buffer, and write from that buffer into your socket (you could also use send and recv, which are socket-specific ways of writing and reading data). The outline would look something like this:

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 语句再次循环,而其他错误代码意味着某些东西已损坏,您需要停止.

Make sure to read the documentation for read and write carefully, especially when handling errors. Some of the error codes mean that you should just try again, for instance just looping again with a continue statement, while others mean something is broken and you need to stop.

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

For sending the file to a socket, there is a system call, sendfile that does just what you want. It tells the kernel to send a file from one file descriptor to another, and then the kernel can take care of the rest. There is a caveat that the source file descriptor must support mmap (as in, be an actual file, not a socket), and the destination must be a socket (so you can't use it to copy files, or send data directly from one socket to another); it is designed to support the usage you describe, of sending a file to a socket. It doesn't help with receiving the file, however; you would need to do the loop yourself for that. I cannot tell you why there is a sendfile call but no analogous recvfile.

注意 sendfile 是 Linux 特定的;它不可移植到其他系统.其他系统通常有自己的 sendfile 版本,但确切的界面可能会有所不同(FreeBSD, Mac OS XSolaris).

Beware that sendfile is Linux specific; it is not portable to other systems. Other systems frequently have their own version of sendfile, but the exact interface may vary (FreeBSD, Mac OS X, Solaris).

在 Linux 2.6.17 中,splice 系统调用被引入,从 2.6 开始.23 是 内部用于实现 sendfilesplice 是比 sendfile 更通用的 API.有关 splicetee 的详细说明,请参阅相当不错的 来自 Linus 本人的解释.他指出如何使用splice基本上就像上面的循环一样,使用readwrite,只是缓冲区在内核中,所以数据不必在内核和用户空间之间传输,甚至可能永远不会通过 CPU(称为零拷贝 I/O").

In Linux 2.6.17, the splice system call was introduced, and as of 2.6.23 is used internally to implement sendfile. splice is a more general purpose API than sendfile. For a good description of splice and tee, see the rather good explanation from Linus himself. He points out how using splice is basically just like the loop above, using read and write, except that the buffer is in the kernel, so the data doesn't have to transferred between the kernel and user space, or may not even ever pass through the CPU (known as "zero-copy I/O").

这篇关于使用 C/C++ (GCC/G++) 在 Linux 中的套接字编程中发送和接收文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆