Linux的拼接(2)在从TCP套接字拼接时是否工作?

我一直在写一个有趣的小程序,在Linux上用C语言通过TCP传输文件。 程序从套接字读取文件并将其写入文件(反之亦然)。 我最初使用读/写和程序正常工作,但后来我了解拼接,并试图试一试。

我用splice编写的代码在从stdin(redirect文件)读取并写入TCP套接字时工作正常,但是从套接​​字读取并写入stdout时,将拼接设置errno立即失败到EINVAL,从而立即失败。 手册页指出,当任何一个描述符都不是pipe道时,EINVAL被设置(不是这种情况),为无法search的stream传递一个偏移量(没有偏移量通过),或者文件系统不支持拼接,这导致我对我的问题:这是否意味着TCP可以pipe道拼接,但不是?

我包含了下面的代码(减去error handling代码),希望我做了一些错误的事情。 它很大程度上基于维基百科拼接的例子 。

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时被splice_all当文件足够大时,由于pipe道已经填满(?),所以我也有一个代码的版本, fork s中读取和写入但是它和这个版本有相同的错误,而且很难阅读。

编辑:我的内核版本是2.6.22.18-co-0.7.3(在XP上运行coLinux)

Solutions Collecting From Web of "Linux的拼接(2)在从TCP套接字拼接时是否工作?"

这是什么内核版本? 从2.6.25开始,Linux已经支持从TCP套接字进行拼接(commit 9c55e01c0 ),所以如果你使用的是早期的版本,那么你是不走运的。

您需要从pipes[0]进行splice_allsplice_allpipes[0]进行单个拼接pipes[1]splice_all用于最后单个拼接读取的字节量)。 原因:管道代表有限的内核内存缓冲区。 所以,如果字节超过了这个splice_all(from, pipes[1], bytes) ,你将永远在你的splice_all(from, pipes[1], bytes)封锁。