对于我的硕士论文项目,我正在使用C语言构建一个与Unix套接字配合工作的API。简单来说,我有两个由它们各自的文件描述符所标识的套接字,在这两个套接字上我调用了
问题现在开始了,因为使用此API的应用程序只知道其中一个套接字,假设是由fd1标识的那个。如果由fd2标识的套接字首先连接,应用程序就无法知道可以向那个套接字进行写入。
我认为最好的选择是使用
看起来很好,但第一个
有没有对Unix文件描述符有更好理解的人可以帮帮我?
编辑:我想进一步阐述API的功能以及应用程序为什么只看到一个fd。
API提供给应用程序调用非常“高级”的
当应用程序调用
现在,如果应用程序使用
此时,我真的很困惑是否需要dup或者只需要整数交换(我对Unix文件描述符的理解仅仅比基础知识多一点)。
O_NONBLOCK
connect()
。在这个点上,我调用了select()
来检查哪一个先连接并准备好进行写入。问题现在开始了,因为使用此API的应用程序只知道其中一个套接字,假设是由fd1标识的那个。如果由fd2标识的套接字首先连接,应用程序就无法知道可以向那个套接字进行写入。
我认为最好的选择是使用
dup()
和/或dup2()
,但据其手册所述,dup()
会创建传递给函数的文件描述符的副本,但是二者引用相同的打开文件描述符,这意味着两者可以互换使用,而dup2()
则关闭替换旧文件描述符的新文件描述符。所以我对会发生什么做了如下假设(伪代码):int fd1, fd2, fd3;
fd1 = socket(x); // what the app is aware of
fd2 = socket(y); // first to connect
fd3 = dup(fd1); // fd1 and fd3 identify the same description
dup2(fd2, fd1); // The description identified by fd2 is now identified by fd1, the description previously identified by fd1 (and fd3) is closed
dup2(fd3, fd2); // The description identified by fd3 (copy of fd1, closed in the line above) is identified by fd2 (which can be closed and reassigned to fd3) since now the the description that was being identified by fd2 is being identified by fd1.
看起来很好,但第一个
dup2()
关闭了fd1,因为它们标识着相同的文件描述符,所以也关闭了fd3。第二个dup2()
运行良好,但它替换了已被第一个关闭的连接的fd,而我希望它继续尝试连接。有没有对Unix文件描述符有更好理解的人可以帮帮我?
编辑:我想进一步阐述API的功能以及应用程序为什么只看到一个fd。
API提供给应用程序调用非常“高级”的
connect()
、select()
和close()
的方式。当应用程序调用
api_connect()
时,它将向函数传递一个指向int的指针(以及所有必要的地址和协议等)。api_connect()
将调用socket()
、bind()
和connect()
,重要的是它将把socket()
的返回值写入通过指针解析的内存中。这就是我所说的“套接字只知道一个fd”的意思。然后,应用程序将调用FD_SET(fd1, write_set)
,调用api_select()
,然后通过调用FD_ISSET(fd1, write_set)
检查fd是否可写。api_select()
的工作方式与select()
差不多,但它有一个计时器,如果连接花费的时间超过一定的时间(因为它是O_NONBLOCK
),就会触发超时。如果发生这种情况,api_select()
将在不同的接口上创建一个新的连接(调用所有必要的socket()
、bind()
和connect()
)。这个连接由一个新的fd-fd2-标识,应用程序不知道,并在API中跟踪。现在,如果应用程序使用
FD_SET(fd1, write_set)
调用api_select()
并且API意识到这是第二个已完成的连接,从而使fd2可写,我希望应用程序使用fd2。问题是应用程序只会在之后调用FD_ISSET(fd1, write_set)
和write(fd1)
,这就是为什么我需要用fd1替换fd2的原因。此时,我真的很困惑是否需要dup或者只需要整数交换(我对Unix文件描述符的理解仅仅比基础知识多一点)。
fd1
和fd3
指向同一个打开的文件,并不意味着关闭其中一个会自动关闭另一个。如果是这样的话,重定向操作将无法实现。 - user4815162342api_select()
之前进行dup(fd1)
并在此副本上工作,会发生什么?如果可能的话,您应该更改API ,使例如api_select()
返回一个fd,并/或提供操作您的fd的函数(例如api_read()
)。 - ensc