C++ 文件描述符和套接字连接

C++ 文件描述符和套接字连接,c++,c,sockets,unix,network-programming,C++,C,Sockets,Unix,Network Programming,我试图理解文件描述符与套接字的关系。根据我的理解,您监听一个特定的文件描述符,一旦连接进入,您接受它,它将返回另一个文件描述符(总共2个),您使用第二个描述符发送/接收数据 我观察到的奇怪行为是,在接受之后,我有3个文件描述符,而不是两个。。。。我不知道为什么会这样 我使用lsof或/proc/pid来观察fd数量的增加 ps:这些是af_unix套接字 编辑:代码 下面是创建scoket的代码 int s, s2, len; socklen_t t; struct so

我试图理解文件描述符与套接字的关系。根据我的理解,您监听一个特定的文件描述符,一旦连接进入,您接受它,它将返回另一个文件描述符(总共2个),您使用第二个描述符发送/接收数据

我观察到的奇怪行为是,在接受之后,我有3个文件描述符,而不是两个。。。。我不知道为什么会这样

我使用lsof或/proc/pid来观察fd数量的增加

ps:这些是af_unix套接字

编辑:代码

下面是创建scoket的代码

   int s, s2,  len;
    socklen_t t;
    struct sockaddr_un local, remote;

    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
    {
            syslog(LOG_ERR,"Failed to create a socket");
            exit(1);
    }
    int flags =  fcntl(s, F_GETFD);
    if (flags == -1)
    {
            syslog(LOG_ERR,"Failed to get socket flags");
            exit(1);
    }

    flags |= FD_CLOEXEC;

    if (fcntl(s, F_SETFD, flags) == -1)
    {
            syslog(LOG_ERR,"Failed to set socket flags");
            exit(1);
    }

    local.sun_family = AF_UNIX;
    strcpy(local.sun_path, SOCK_PATH.c_str());

    unlink(local.sun_path);
    len = strlen(local.sun_path) + sizeof(local.sun_family);

    if (bind(s, (struct sockaddr *)&local, len) == -1)
    {
            syslog(LOG_ERR,"Failed to bind socket");
            exit(1);
    }


    if (listen(s, 5) == -1)
    {
            syslog(LOG_ERR,"Failed to listen at socket");
            exit(1);
    }
接受连接的代码

我正在通过gdb,在接受之后,fd变成了3。操作系统是FedoraCore13

我需要验证这一点的原因是我不希望我的流程保留FD;由于它是一个守护进程,随着时间的推移,它可能会使系统陷入困境

这确实看起来很奇怪。关闭已接受的连接后,我仍然剩下两个fd。 i、 一个听一个鬼。。。更奇怪的是,即使建立了10个连接,在所有连接结束时,只有一个幽灵fd仍然关闭

它听起来确实像是特定于操作系统的实现

干杯

请输入更多代码

但我猜您正在查看套接字的操作系统实现。
它可能使用一个文件描述符进行读取,另一个用于写入(但这只是猜测)


操作系统在
/proc/pid
中做什么对你有什么关系?那里的东西实际上不适合你直接使用。

你是对的,它是两个。你一定把第三个和别的东西搞混了


如果没有更多信息,很难提供帮助。

调试此类问题的最简单方法是在实用程序下运行应用程序。检查进行了哪些系统调用,参数和返回值是什么,并将其与使用的文件描述符相关联。

您的额外文件描述符很可能与
syslog
相关。Syslog必须打开syslogd的套接字才能报告消息。除非明确调用
openlog
,否则在第一次调用
syslog
时会打开此套接字,由于在出现错误之前您不会调用
syslog
,因此您很可能观察到了
syslog
的副作用。

是否有一小段代码重现了这个问题?如果没有更多代码和您报告的症状证据,很难说。(你会在接受后立即进行系统日志记录吗?那会烧掉一个fd。)然而,
lsof
/proc/$pid/fd
应该让你确定这个意外的fd是绑定的还是接受的套接字的副本……听起来gdb好像在做什么。这正是问题所在。谢谢!:)另外:有一个对openlog的显式调用,但是套接字出现在第一个syslog调用之后。
    while (1)
    {
            stat =0;
            execReturn=0;
            t = len;
            read_fds = master;
            if (select(fdmax+1, &read_fds, NULL, NULL, &tv) != -1)
            {
                    if(FD_ISSET(s,&read_fds))
                    {
                            //Accept new connection
                            //fork child -> fork grand child
                            //child will return value back

                            if ((s2 = accept(s, (struct sockaddr*)&remote, &t)) == -1)
                            {
                                    syslog(LOG_ERR,"Failed to acceptconnection  at socket");
                                    exit(1);
                            }