当前位置: 首页 > 面试题库 >

从TCP套接字进行拼接时,Linux的splice(2)是否起作用?

贡英华
2023-03-14
问题内容

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

当我从stdin(重定向文件)读取并写入TCP套接字时,我用splice编写的代码可以完美地工作,但是当从套接字读取并写入stdout时,将spr将errno设置为EINVAL会立即失败。手册页指出,当两个描述符都不是管道(不是这种情况),为无法查找的流传递了偏移(没有传递偏移)或文件系统不支持拼接时,设置了EINVAL。我的问题:这是否意味着TCP可以
管道进行拼接,但不能 进行 拼接?

我包括下面的代码(减去错误处理代码),希望我做错了什么。它很大程度上基于Wikipedia的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可以从以下位置从管道读取和写入相同的时间,但它具有与此版本相同的错误,并且较难阅读。

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


问题答案:

这是什么内核版本?从2.6.25(提交9c55e01c0)开始,Linux就支持从TCP套接字进行拼接,因此,如果您使用的是较早的版本,那么您将很不走运。



 类似资料:
  • 本文介绍:http://tldp.org/howto/tcp-keepalive-howto/overview.html 它指出TCP保持有效的原因是: null TCP keepalive对于上面的情况仍然是必要的吗?

  • 在套接字最终接受另一端消失的情况下,什么指定了这个超时?是操作系统(Ubuntu 11.04),还是来自TCP/IP规范,还是套接字配置选项?

  • 问题内容: 如何尝试在超时的情况下从套接字读取数据?我知道,选择,pselect,轮询具有超时字段,但是使用它们会禁用tcp reno堆栈中的“ tcp快速路径”。 我唯一的想法是在循环中使用recv(fd,…,MSG_DONTWAIT) 问题答案: 您可以使用setsockopt函数来设置接收操作的超时: SO_RCVTIMEO 设置超时值,该值指定输入函数完成之前等待的最长时间。它接受一个ti

  • 问题内容: 任何人都可以通过TCP发送Ascii msg的示例给我(在网上找不到示例) 谢谢, 射线。 问题答案: 这是一个写入和读取回显服务器的示例。 简化摘录:

  • 问题内容: 是否可以在IP协议下使用ICMP套接字?也许像: 我应该在 字段中输入什么?我看到了一些使用SOCK_RAW的示例,但是这是否会阻止OS处理IP协议呢? 还有一件事。由于该协议不涉及任何端口,操作系统如何知道他应该向哪个进程发送ICMP数据报? 问题答案: 是的,这是可能的,因为该命令执行ICMP。 要找出所涉及的系统调用,您可以使用该命令(在根目录下)。 您也可以浏览该命令的源代码,