带有线程的 Linux 套接字文件描述符

Linux Socket file descriptor with threads

本文关键字:文件 描述 套接字 Linux 线程      更新时间:2023-10-16

考虑以下情况:一个线程(我们称之为A)初始化,使用listen()设置套接字状态,然后等待accept()。连接到达 A 套接字,accept()返回有效的 fd。创建新线程 (B)(使用 std::thread),并将获取的 fd 传递给线程 B 中运行的可调用对象 witch.读取(使用 read())fd 失败,errno设置为 9 EBADFD 。线程 A 在 B 上调用join()。当 B 未生成且使用 fd 时(仍然通过相同的可调用对象),读取完成且不会失败。为什么?下面是一些代码来说明这种情况。

BaseFun::BaseFun(char* bufferAdr, int socket):
    socket_fd(socket)
    buffer(bufferAdr)
{}
BaseFun::~BaseFun()
{
    close(socket_fd);
}
char* BaseFun::buffer_read()
{
    if(read(socket_fd, buffer, BUFF_SIZE-1) < 0) {
        std::cout<<"ERROR while READn"<<"ERRNO: "<<errno<<"n"<<"FD: "<<socket_fd<<"n";
    }
    return buffer;
}
DisplayMsgFun::DisplayMsgFun(char* buffer, int socket) :
    BaseFun(buffer, socket)
{}
void DisplayMsgFunFun::operator()()
{
    std::cout<<"Message:nt"<<buffer_read()<<"nENDn";
}

上面调用的代码段:

void Server::server_run()
{
    sockaddr_in client_addr;
    socklen_t c_len = sizeof(client_addr);
    client_fd = accept(sock_fd, (sockaddr*)&client_addr, &c_len);
    DisplayMsgFun dm(server_buffers->front().data(), client_fd);
    std::thread job(dm);
    job.join();
}

main()

int main()
{
    Server srv(PORT);
    if (srv.server_create()) {
        std::cout << "Server bind!n";
        srv.server_run();
    }
    else {
        std::cout << "Bind fail! ERRNO: "<<errno<<"n";
        return -1;
    }
    return 0;
}

您似乎正在将DisplayMsgFun对象的副本传递给std::thread构造函数,这意味着原始副本将被销毁,并根据您的析构函数自动调用::close