关闭套接字时接收窗口有数据滞留,将当即向对端发送TCP RST。c++
对端接收TCP RST后:socket
下面用代码进行验证(使用SIren库)。tcp
#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
#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
#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
#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