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