Code: Select all
#include
#include
#include
#include
#include
#include
#include
void
do_accept(int lfd)
{
sockaddr_in sin;
socklen_t sinlen = sizeof(sin);
int fd = accept(lfd, (sockaddr *) &sin, &sinlen);
close(lfd);
char buf[128];
errno = 0;
while (read(fd, buf, sizeof(buf)) > 0)
;
close(fd);
}
void
do_poll(int cfd, int wake)
{
pollfd pfds[2];
pfds[0].fd = cfd;
pfds[0].events = POLLIN;
pfds[1].fd = wake;
pfds[1].events = POLLIN;
poll(pfds, 2, -1);
}
int
main()
{
int lfd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in sin{};
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
bind(lfd, (sockaddr *)&sin, sizeof(sin));
listen(lfd, 5);
socklen_t sinlen = sizeof(sin);
getsockname(lfd, (sockaddr *)&sin, &sinlen);
uint16_t port = ntohs(sin.sin_port);
std::println("listening on port {}", port);
std::thread acceptor(do_accept, lfd);
int cfd = socket(AF_INET, SOCK_STREAM, 0);
if (connect(cfd, (sockaddr *)&sin, sinlen)) {
perror("connect");
exit(1);
}
int selfpipe[2];
pipe(selfpipe);
std::thread poller(do_poll, cfd, selfpipe[0]);
poll(nullptr, 0, 1000);
//shutdown(cfd, SHUT_WR); // Works if you uncomment
close(cfd); // Would like this to send EOF
acceptor.join(); // Would like this to return
std::println("Will never get this far");
write(selfpipe[1], "", 1);
poller.join();
}
< /code>
Dieses Programm erstellt einen "Ghost Socket", dessen Dateideskriptor damit zugeordnet ist. Sie können dies mit den Befehlen ss
$ lsof -c closepoll -nPa -i tcp -Tqs
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
closepoll 918275 user 5u IPv4 8515786 0t0 TCP 127.0.0.1:41503->127.0.0.1:57248 (ESTABLISHED QR=0 QS=0)
$ ss -antp "sport 57248 or dport 57248"
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 127.0.0.1:57248 127.0.0.1:41503
ESTAB 0 0 127.0.0.1:41503 127.0.0.1:57248 users:(("closepoll",pid=918275,fd=5))
< /code>
Kein Dateideskriptor entspricht dem lokalen Port 57248, obwohl es sich um eine Verbindung im festgelegten Zustand handelt. Sollte es nicht eingeben fin_wait_1, wenn der letzte Dateideskriptor geschlossen ist? und wie kann ich dieses Problem vermeiden?