Linux下如何重现Connection reset by peer、Broken pipe错误(2)

关闭套接字时接收窗口有数据滞留,将当即向对端发送TCP RST。c++

对端接收TCP RST后:socket

  1. 进行读操做:
    1. 若已接收TCP FIN,返回0。
    2. 若未接收TCP FIN,返回错误“Connection reset by peer”。
  2. 进行写操做:
    1. 若已接收TCP FIN,返回错误“Broken pipe”。
    2. 若未接收TCP FIN,返回错误“Connection reset by peer”。

下面用代码进行验证(使用SIren库)。tcp

状况1.1

#include <cassert>
#include <cstdio>

#include <siren/ip_endpoint.h>
#include <siren/loop.h>
#include <siren/stream.h>
#include <siren/tcp_socket.h>


using namespace siren;


int
main()
{
    Loop l(16 * 1024);

    l.createFiber([&] () -> void {
        TCPSocket ss(&l);
        ss.setReuseAddress(true);
        ss.listen(IPEndpoint(0, 0));
        IPEndpoint ipe = ss.getLocalEndpoint();
        Event e = l.makeEvent();

        l.createFiber([&] () -> void {
            /* mark */ std::puts("step 2");
            TCPSocket cs(&l);
            cs.connect(ipe);
            e.waitFor();
            /* mark */ std::puts("step 5");
            cs.setNoDelay(true);
            cs.closeWrite(); // 发送TCP FIN
            Stream s;
            s.reserveBuffer(1); // 缓冲区大小为1
            cs.read(&s); // 接收窗口还有2字节未读出,cs析构时调用close()将向对端发送TCP RST
            /* mark */ std::puts("step 6");
        });

        /* mark */ std::puts("step 1");
        TCPSocket cs = ss.accept();
        /* mark */ std::puts("step 3");
        e.trigger();
        cs.setNoDelay(true);
        Stream s;
        s.write("abc", 3); // 数据大小为3
        cs.write(&s);
        /* mark */ std::puts("step 4");
        l.usleep(1000000); // 接收对端发送的TCP FIN和TCP RST
        /* mark */ std::puts("step 7");
        s.reserveBuffer(1);
        assert(cs.read(&s) == 0);  // 无异常,无数据
        /* mark */ std::puts("step 8");
    });

    l.run();
    return 0;
}

编译运行oop

# g++ -std=c++14 test.cc -lsiren -lpthread && ./a.out
step 1
step 2
step 3
step 4
step 5
step 6
step 7
step 8

状况1.2

#include <cstdio>

#include <siren/ip_endpoint.h>
#include <siren/loop.h>
#include <siren/stream.h>
#include <siren/tcp_socket.h>


using namespace siren;


int
main()
{
    Loop l(16 * 1024);

    l.createFiber([&] () -> void {
        TCPSocket ss(&l);
        ss.setReuseAddress(true);
        ss.listen(IPEndpoint(0, 0));
        IPEndpoint ipe = ss.getLocalEndpoint();
        Event e = l.makeEvent();

        l.createFiber([&] () -> void {
            /* mark */ std::puts("step 2");
            TCPSocket cs(&l);
            cs.connect(ipe);
            e.waitFor();
            /* mark */ std::puts("step 5");
            cs.setNoDelay(true);
            Stream s;
            s.reserveBuffer(1); // 缓冲区大小为1
            cs.read(&s); // 接收窗口还有2字节未读出,cs析构时调用close()将向对端发送TCP RST
            /* mark */ std::puts("step 6");
        });

        /* mark */ std::puts("step 1");
        TCPSocket cs = ss.accept();
        /* mark */ std::puts("step 3");
        e.trigger();
        cs.setNoDelay(true);
        Stream s;
        s.write("abc", 3); // 数据大小为3
        cs.write(&s);
        /* mark */ std::puts("step 4");
        l.usleep(1000000); // 接收对端发送的TCP RST
        /* mark */ std::puts("step 7");
        s.reserveBuffer(1);
        cs.read(&s);  // 抛出异常
        /* mark */ std::puts("step 8");
    });

    l.run();
    return 0;
}

编译运行spa

step 1
step 2
step 3
step 4
step 5
step 6
step 7
terminate called after throwing an instance of 'std::system_error'
  what():  read() failed: Connection reset by peer
Aborted

状况2.1

#include <cstdio>

#include <siren/ip_endpoint.h>
#include <siren/loop.h>
#include <siren/stream.h>
#include <siren/tcp_socket.h>


using namespace siren;


int
main()
{
    Loop l(16 * 1024);

    l.createFiber([&] () -> void {
        TCPSocket ss(&l);
        ss.setReuseAddress(true);
        ss.listen(IPEndpoint(0, 0));
        IPEndpoint ipe = ss.getLocalEndpoint();
        Event e = l.makeEvent();

        l.createFiber([&] () -> void {
            /* mark */ std::puts("step 2");
            TCPSocket cs(&l);
            cs.connect(ipe);
            e.waitFor();
            /* mark */ std::puts("step 5");
            cs.setNoDelay(true);
            cs.closeWrite(); // 发送TCP FIN
            Stream s;
            s.reserveBuffer(1); // 缓冲区大小为1
            cs.read(&s); // 接收窗口还有2字节未读出,cs析构时调用close()将向对端发送TCP RST
            /* mark */ std::puts("step 6");
        });

        /* mark */ std::puts("step 1");
        TCPSocket cs = ss.accept();
        /* mark */ std::puts("step 3");
        e.trigger();
        cs.setNoDelay(true);
        Stream s;
        s.write("abc", 3); // 数据大小为3
        cs.write(&s);
        /* mark */ std::puts("step 4");
        l.usleep(1000000); // 接收对端发送的TCP FIN和TCP RST
        /* mark */ std::puts("step 7");
        s.write("a", 1);
        cs.write(&s);  // 抛出异常
        /* mark */ std::puts("step 8");
    });

    l.run();
    return 0;
}

编译运行code

# g++ -std=c++14 test.cc -lsiren -lpthread && ./a.out
step 1
step 2
step 3
step 4
step 5
step 6
step 7
terminate called after throwing an instance of 'std::system_error'
  what():  send() failed: Broken pipe
Aborted

状况2.2

#include <cstdio>

#include <siren/ip_endpoint.h>
#include <siren/loop.h>
#include <siren/stream.h>
#include <siren/tcp_socket.h>


using namespace siren;


int
main()
{
    Loop l(16 * 1024);

    l.createFiber([&] () -> void {
        TCPSocket ss(&l);
        ss.setReuseAddress(true);
        ss.listen(IPEndpoint(0, 0));
        IPEndpoint ipe = ss.getLocalEndpoint();
        Event e = l.makeEvent();

        l.createFiber([&] () -> void {
            /* mark */ std::puts("step 2");
            TCPSocket cs(&l);
            cs.connect(ipe);
            e.waitFor();
            /* mark */ std::puts("step 5");
            cs.setNoDelay(true);
            Stream s;
            s.reserveBuffer(1); // 缓冲区大小为1
            cs.read(&s); // 接收窗口还有2字节未读出,cs析构时调用close()将向对端发送TCP RST
            /* mark */ std::puts("step 6");
        });

        /* mark */ std::puts("step 1");
        TCPSocket cs = ss.accept();
        /* mark */ std::puts("step 3");
        e.trigger();
        cs.setNoDelay(true);
        Stream s;
        s.write("abc", 3); // 数据大小为3
        cs.write(&s);
        /* mark */ std::puts("step 4");
        l.usleep(1000000); // 接收对端发送的TCP RST
        /* mark */ std::puts("step 7");
        s.write("a", 1);
        cs.write(&s);  // 抛出异常
        /* mark */ std::puts("step 8");
    });

    l.run();
    return 0;
}

编译运行ip

# g++ -std=c++14 test.cc -lsiren -lpthread && ./a.out
step 1
step 2
step 3
step 4
step 5
step 6
step 7
terminate called after throwing an instance of 'std::system_error'
  what():  send() failed: Connection reset by peer
Aborted
相关文章
相关标签/搜索