我一直在写一个有趣的小程序,通过TCP在Linux上的C语言中传输文件。程序从套接字读取文件并将其写入文件(反之亦然)。我最初使用读/写,程序运行正常,但后来我了解到
splice
想试试看。
我用splice编写的代码在从stdin(重定向文件)读取和写入TCP套接字时工作得很好,但在从socket读取和写入stdout时,splice设置errno设置为einfal时会立即失败。该手册页指出,当两个描述符都不是管道时(不是这样),将为无法查找的流传递偏移量(未传递偏移量),或者文件系统不支持拼接,这就引出了我的问题:这是否意味着TCP可以拼接
从
一根管子,但不是
到
?
我将下面的代码(减去错误处理代码)包括在内,希望我刚刚做了一些错误。它主要基于
Wikipedia example for splice
.
static void splice_all(int from, int to, long long bytes)
{
long long bytes_remaining;
long result;
bytes_remaining = bytes;
while (bytes_remaining > 0) {
result = splice(
from, NULL,
to, NULL,
bytes_remaining,
SPLICE_F_MOVE | SPLICE_F_MORE
);
if (result == -1)
die("splice_all: splice");
bytes_remaining -= result;
}
}
static void transfer(int from, int to, long long bytes)
{
int result;
int pipes[2];
result = pipe(pipes);
if (result == -1)
die("transfer: pipe");
splice_all(from, pipes[1], bytes);
splice_all(pipes[0], to, bytes);
close(from);
close(pipes[1]);
close(pipes[0]);
close(to);
}
从旁注来看,我认为上面的内容会在第一个
splice_all
当文件足够大时,由于管道填充(?),所以我还有一个版本的代码,
fork
s可以同时从管道中读写,但它的错误与此版本相同,而且更难读取。
编辑:我的内核版本是2.6.22.18-co-0.7.3(在XP上运行colinux)。