Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从管道到TCP缓冲区的拼接()?_Tcp_Linux Kernel_Pipe_Splice_Zero Copy - Fatal编程技术网

从管道到TCP缓冲区的拼接()?

从管道到TCP缓冲区的拼接()?,tcp,linux-kernel,pipe,splice,zero-copy,Tcp,Linux Kernel,Pipe,Splice,Zero Copy,linuxquestions.org的xpost,抱歉 我编写了一个小测试程序,以查看使用splice()是否有利于简单代理,但从套接字的另一端读取从管道拼接到TCP套接字的数据总是需要200毫秒 下面是测试它的Perl程序: package test_pipes_2; use strict; use warnings; use IO::Handle(); use POSIX qw(:errno_h); use Time::HiRes qw(time); use English qw(-no_m

linuxquestions.org的xpost,抱歉

我编写了一个小测试程序,以查看使用splice()是否有利于简单代理,但从套接字的另一端读取从管道拼接到TCP套接字的数据总是需要200毫秒

下面是测试它的Perl程序:

package test_pipes_2;
use strict;
use warnings;
use IO::Handle();
use POSIX qw(:errno_h);
use Time::HiRes qw(time);
use English qw(-no_match_vars);
use IO::Socket::INET;
use Socket qw(IPPROTO_TCP TCP_NODELAY);

__PACKAGE__->run if not caller;

sub run {
    my( $class ) = @ARG;

    pipe my $parent_reader, my $child_writer;
    my $parent_reader_fd = fileno $parent_reader;
    my $child_writer_fd  = fileno $child_writer;
    pipe my $child_reader,  my $parent_writer;
    my $child_reader_fd  = fileno $child_reader;
    my $parent_writer_fd = fileno $parent_writer;

    my $server = IO::Socket::INET->new(
        LocalAddr   => '127.0.0.1:9000',
        Type        => SOCK_STREAM,
        Listen      => 5,
        ReuseAddr   => 1,
        Blocking    => 1,
    ) || die $OS_ERROR;

    my $client_browser = IO::Socket::INET->new(
        PeerAddr   => '127.0.0.1:9000',
        Type        => SOCK_STREAM,
        Blocking    => 1,
    ) || die $OS_ERROR;
#   setsockopt $client_browser, IPPROTO_TCP, TCP_NODELAY, 1;
    my $client_browser_fd = fileno $client_browser;

    my $server_browser = $server->accept() || die $OS_ERROR;
#   setsockopt $server_browser, IPPROTO_TCP, TCP_NODELAY, 1;
    my $server_browser_fd = fileno $server_browser;

    for( 1 .. 3 ) { #  100_000
        syswrite $client_browser, "HTTP/1.1 GET /foo/\r\nLocation: foo.com\r\n\r\n";
        $server_browser->recv( my $request1, 4096, POSIX::MSG_PEEK );

        syscall 313, $server_browser_fd, undef, $child_writer_fd, undef, 4096, 1;
        sysread $parent_reader, my $request2, 4096;

        my $response = "200 OK\n<head><title>html</title></head><body>body from $PID</body>";
        syswrite $parent_writer, $response;
        syscall 313, $child_reader_fd, undef, $server_browser_fd, undef, 4096, 1;
#       syswrite $server_browser, "\n"; # eliminates delay, adds syscall...
        sysread $client_browser, my $response1, 4096;
#       chomp $response1;

        if( $response1 ne $response ) {
            warn 'Got wrong response: ', $response1 // 'undef';
            no warnings 'once';
            $DB::single = 1;
        }
    }
}

1;
包装测试\u管道\u 2;
严格使用;
使用警告;
使用IO::Handle();
使用POSIXQW(:errno_h);
使用时间:雇佣qw(时间);
使用英语qw(-no_match_vars);
使用IO::Socket::INET;
使用套接字qw(IPPROTO_TCP_节点);
__如果不是调用者,则运行包;
分段{
我的($class)=@ARG;
管道我的$parent\u reader,我的$child\u writer;
my$parent\u reader\u fd=fileno$parent\u reader;
my$child\u writer\u fd=fileno$child\u writer;
管我的$child\u reader,我的$parent\u writer;
my$child\u reader\u fd=fileno$child\u reader;
my$parent\u writer\u fd=fileno$parent\u writer;
my$server=IO::Socket::INET->new(
LocalAddr=>“127.0.0.1:9000”,
类型=>SOCK\u流,
听着=>5,
ReuseAddr=>1,
阻塞=>1,
)| | die$OS| u错误;
我的$client\u browser=IO::Socket::INET->new(
PeerAddr=>'127.0.0.1:9000',
类型=>SOCK\u流,
阻塞=>1,
)| | die$OS| u错误;
#设置锁定选项$client_browser,IPPROTO_TCP,TCP_NODELAY,1;
my$client\u browser\u fd=fileno$client\u browser;
my$server|u browser=$server->accept()|| die$OS|u错误;
#设置SOCKOPT$server_browser,IPPROTO_TCP,TCP_节点延迟,1;
my$server\u browser\u fd=fileno$server\u browser;
对于(1..3){100#000
syswrite$client\u浏览器,“HTTP/1.1 GET/foo/\r\n位置:foo.com\r\n\r\n”;
$server_browser->recv(我的$request14096,POSIX::MSG_PEEK);
系统调用313,$server\u browser\u fd,undf,$child\u writer\u fd,undf,4096,1;
sysread$parent_reader,my$request24096;
my$response=“200 OK\nhtmlbody from$PID”;
syswrite$parent\u writer$response;
系统调用313,$child\u reader\u fd,undf,$server\u browser\u fd,undf,4096,1;
#syswrite$server_浏览器,“\n”#消除延迟,添加系统调用。。。
sysread$client_browser,my$response1,4096;
#咀嚼$response1;
如果($response1 ne$response){
警告“响应错误:”,$response1//'undef';
没有“一次”警告;
$DB::single=1;
}
}
}
1.
下面是strace输出的示例:

socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 8 <0.000010>
setsockopt(8, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 <0.000006>
bind(8, {sa_family=AF_INET, sin_port=htons(9000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0 <0.000008>
listen(8, 5)                            = 0 <0.000008>
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 9 <0.000006>
connect(9, {sa_family=AF_INET, sin_port=htons(9000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0 <0.000037>
accept(8, {sa_family=AF_INET, sin_port=htons(49361), sin_addr=inet_addr("127.0.0.1")}, [16]) = 10 <0.000007>
write(9, "HTTP/1.1 GET /foo/\r\nLocation: foo.com\r\n\r\n"..., 41) = 41 <0.000014>
recvfrom(10, "HTTP/1.1 GET /foo/\r\nLocation: foo.com\r\n\r\n"..., 4096, MSG_PEEK, {sa_family=0x8b60 /* AF_??? */, sa_data="(\10\2\0\300\321\177\0\0\1\0\0\0\0"...}, [0]) = 41 <0.000007>
splice(0xa, 0, 0x5, 0, 0x1000, 0x1)     = 41 <0.000007>
read(4, "HTTP/1.1 GET /foo/\r\nLocation: foo.com\r\n\r\n"..., 4096) = 41 <0.000005>
write(7, "200 OK\n<head><title>html</title></head><body>body from 14019</body>"..., 67) = 67 <0.000005>
splice(0x6, 0, 0xa, 0, 0x1000, 0x1)     = 67 <0.000007>
read(9, "200 OK\n<head><title>html</title></head><body>body from 14019</body>"..., 4096) = 67 <0.200331>
write(9, "HTTP/1.1 GET /foo/\r\nLocation: foo.com\r\n\r\n"..., 41) = 41 <0.000016>
recvfrom(10, "HTTP/1.1 GET /foo/\r\nLocation: foo.com\r\n\r\n"..., 4096, MSG_PEEK, {sa_family=0x8b60 /* AF_??? */, sa_data="(\10\2\0\300\321\177\0\0\1\0\0\0\0"...}, [0]) = 41 <0.000008>
splice(0xa, 0, 0x5, 0, 0x1000, 0x1)     = 41 <0.000006>
read(4, "HTTP/1.1 GET /foo/\r\nLocation: foo.com\r\n\r\n"..., 4096) = 41 <0.000005>
write(7, "200 OK\n<head><title>html</title></head><body>body from 14019</body>"..., 67) = 67 <0.000005>
splice(0x6, 0, 0xa, 0, 0x1000, 0x1)     = 67 <0.000006>
read(9, "200 OK\n<head><title>html</title></head><body>body from 14019</body>"..., 4096) = 67 <0.200622>
write(9, "HTTP/1.1 GET /foo/\r\nLocation: foo.com\r\n\r\n"..., 41) = 41 <0.000018>
recvfrom(10, "HTTP/1.1 GET /foo/\r\nLocation: foo.com\r\n\r\n"..., 4096, MSG_PEEK, {sa_family=0x8b60 /* AF_??? */, sa_data="(\10\2\0\300\321\177\0\0\1\0\0\0\0"...}, [0]) = 41 <0.000007>
splice(0xa, 0, 0x5, 0, 0x1000, 0x1)     = 41 <0.000006>
read(4, "HTTP/1.1 GET /foo/\r\nLocation: foo.com\r\n\r\n"..., 4096) = 41 <0.000005>
write(7, "200 OK\n<head><title>html</title></head><body>body from 14019</body>"..., 67) = 67 <0.000005>
splice(0x6, 0, 0xa, 0, 0x1000, 0x1)     = 67 <0.000005>
read(9, "200 OK\n<head><title>html</title></head><body>body from 14019</body>"..., 4096) = 67 <0.200649
socket(PF_INET、SOCK_STREAM、IPPROTO_TCP)=8
setsockopt(8,SOL_套接字,SO_REUSEADDR[1],4)=0
bind(8,{sa_family=AF_INET,sin_port=htons(9000),sin_addr=INET_addr(“127.0.0.1”)},16)=0
听(8,5)=0
套接字(PF_INET、SOCK_STREAM、IPPROTO_TCP)=9
连接(9,{sa_family=AF_INET,sin_port=htons(9000),sin_addr=INET_addr(“127.0.0.1”)},16)=0
接受(8,{sa_family=AF_INET,sin_port=htons(49361),sin_addr=INET_addr(“127.0.0.1”)},[16])=10
写(9,“HTTP/1.1get/foo/\r\n位置:foo.com\r\n\r\n”…,41)=41
recvfrom(10,“HTTP/1.1get/foo/\r\n位置:foo.com\r\n\r\n”…,4096,MSG_PEEK,{sa_family=0x8b60/*AF_???*/,sa_data=“(\10\2\0\300\321\177\0\0\1\0\0\0”…},[0])41
拼接(0xa、0、0x5、0、0x1000、0x1)=41
读取(4,“HTTP/1.1get/foo/\r\n位置:foo.com\r\n\r\n”…,4096)=41
写入(7,“200正常\nhtmlbody从14019开始”…,67)=67
拼接(0x6,0,0xa,0,0x1000,0x1)=67
读取(9,“200正常\nhtmlbody从14019开始”…,4096)=67
写(9,“HTTP/1.1get/foo/\r\n位置:foo.com\r\n\r\n”…,41)=41
recvfrom(10,“HTTP/1.1get/foo/\r\n位置:foo.com\r\n\r\n”…,4096,MSG_PEEK,{sa_family=0x8b60/*AF_???*/,sa_data=“(\10\2\0\300\321\177\0\0\1\0\0\0”…},[0])41
拼接(0xa、0、0x5、0、0x1000、0x1)=41
读取(4,“HTTP/1.1get/foo/\r\n位置:foo.com\r\n\r\n”…,4096)=41
写入(7,“200正常\nhtmlbody从14019开始”…,67)=67
拼接(0x6,0,0xa,0,0x1000,0x1)=67
读取(9,“200正常\nhtmlbody从14019开始”…,4096)=67
写(9,“HTTP/1.1get/foo/\r\n位置:foo.com\r\n\r\n”…,41)=41
recvfrom(10,“HTTP/1.1get/foo/\r\n位置:foo.com\r\n\r\n”…,4096,MSG_PEEK,{sa_family=0x8b60/*AF_???*/,sa_data=“(\10\2\0\300\321\177\0\0\1\0\0\0”…},[0])41
拼接(0xa、0、0x5、0、0x1000、0x1)=41
读取(4,“HTTP/1.1get/foo/\r\n位置:foo.com\r\n\r\n”…,4096)=41
写入(7,“200正常\nhtmlbody从14019开始”…,67)=67
拼接(0x6,0,0xa,0,0x1000,0x1)=67

读取(9,“200正常\nhtmlbody从14019开始”…,4096)=67如果取消注释行设置
TCP_NODELAY
,会发生什么情况?即使设置了TCP_NODELAY,它也会以相同的方式运行。它的行为就像我在$server_浏览器套接字上设置了TCP_CORK一样。经过更多的代码读取和实验,我确定如果我将第二次调用的len更改为splice,则它会响应的长度没有200毫秒的暂停。但是在我的实际使用中,发送和拼接将在两个单独的过程中发生,这使得很难准确拼接发送的数量。这似乎不是发送文件的常见用法的问题,因为知道文件大小很简单…当然,我在一周后发现了这一点…什么如果您取消注释行设置
TCP_NODELAY
,则会发生这种情况。即使设置了TCP_NODELAY,它也会以相同的方式运行。它的行为就像我在$server_浏览器套接字上设置了TCP_CORK一样。经过更多的代码读取和实验,我确定如果我将第二次调用的len更改为响应的长度,它就没有响应200毫秒的暂停。然而,在我的实际使用中,发送和拼接将在两个单独的过程中发生,这使得很难准确拼接发送的数量。这似乎不是发送文件的常见用法的问题,因为知道文件大小很简单……当然,我在一周后发现了这一点。。。