简体   繁体   English

有没有办法获得套接字描述符,因为哪个select()调用返回EBADF?

[英]Is there any way to get the socket descriptor due to which select() call is returning EBADF?

I have a code in which I am using select() function call to poll a list of sockets added to readfds set for any incoming data. 我有一个代码,我在其中使用select()函数调用轮询添加到为任何传入数据设置的readfds的套接字列表。

while(1) {
    ret = select(n,&readfds,NULL,NULL,&tv);
    if(ret == -1) {
        perror("Select Failed");
    } else if (ret == 0){
        printf("Select Timeout\n");
    } else {
           recv(clientSocket, buffer, 1024, 0);
           printf("Data received: %s",buffer);
    }
}

I have so many sockets added to readfds list. 我在readfds列表中添加了很多套接字。 There is another thread in my code which is closing a socket in readfds list (This removal of socket from the list is not expected behavior). 我的代码中有另一个线程正在关闭readfds列表中的套接字(从列表中删除套接字不是预期的行为)。 So if the socket is getting removed in another thread, above while loop is throwing "Select Failed : Bad file descriptor". 因此,如果套接字在另一个线程中被删除,则上面的循环正在抛出“选择失败:错误的文件描述符”。

1) One way to avoid this is to fix the bug in other thread to stop removal of the socket from the list 1)避免这种情况的一种方法是修复其他线程中的错误以阻止从列表中删除套接字

2) Another way is to get the socket which is giving bad file descriptor error in select function call and remove that from the list of sockets mentioned in readfds (I can add the same socket to the list again in another part of the program). 2)另一种方法是在select函数调用中获取给出错误的文件描述符错误的套接字,并从readfds中提到的套接字列表中删除它(我可以在程序的另一部分再次将相同的套接字添加到列表中)。

I am trying for the first option. 我正在尝试第一种选择。 Mean while I also wanted to know, is there any way to get the socket descriptor due to which select() call is returning EBADF ? 虽然我也想知道,有没有办法获得套接字描述符,因为哪个select()调用返回EBADF?

  1. Select won't support more than FD_SETSIZE number of descriptors due to size limit of fd_set data structure. 由于fd_set数据结构的大小限制,选择将不支持超过FD_SETSIZE描述符的数量。 Often FD_SETSIZE is 1024. FD_SETSIZE通常是1024。
  2. The way your posted code use Select is problematic. 您发布的代码使用Select的方式存在问题。 Since select modifies the passed fd_sets so none of them can be reused, you need to update fd_set and max fd number each time you prepare for Select call. 由于select修改了传递的fd_sets,因此不能重复使用它们,每次准备Select调用时都需要更新fd_set和max fd数。
  3. Select doesn't support multithreaded use very well because it's not designed so. Select不能很好地支持多线程使用,因为它不是这样设计的。 According to man select: 根据男人选择:

Multithreaded applications 多线程应用程序

If a file descriptor being monitored by select() is closed in another thread, the result is unspecified. 如果select()监视的文件描述符在另一个线程中关闭,则结果未指定。 On some UNIX systems, select() unblocks and returns, with an indication that the file descriptor is ready (a subsequent I/O operation will likely fail with an error, unless another the file descriptor reopened between the time select() returned and the I/O operations was performed). 在某些UNIX系统上,select()取消阻塞并返回,并指示文件描述符已准备就绪(后续I / O操作可能会因错误而失败,除非另一个文件描述符在返回的时间select()和执行了I / O操作)。 On Linux (and some other systems), closing the file descriptor in another thread has no effect on select(). 在Linux(以及其他一些系统)上,关闭另一个线程中的文件描述符对select()没有影响。 In summary, any application that relies on a partic‐ ular behavior in this scenario must be considered buggy. 总之,任何依赖于此场景中特定行为的应用程序都必须被视为错误。

  1. Try using epoll which is more modern and back it with a thread pool. 尝试使用更现代的epoll并使用线程池备份它。

A useful guide is http://www.ulduzsoft.com/2014/01/select-poll-epoll-practical-difference-for-system-architects/ . 一个有用的指南是http://www.ulduzsoft.com/2014/01/select-poll-epoll-practical-difference-for-system-architects/

If another thread is closing a filedescriptor, and you want to use the same descriptor in main thread (select()), you have in theory a "race condition". 如果另一个线程正在关闭文件描述符,并且您想在主线程(select())中使用相同的描述符,那么理论上您就具有“竞争条件”。 Using the same resource in more than one thread at any given time. 在任何给定时间在多个线程中使用相同的资源。

You should protect the filedescriptor references, just like you protect concurrent memory access. 您应该保护filedescriptor引用,就像保护并发内存访问一样。 The filedescriptor number can be reused on next accept/connect/open call, causing inconsistency with your current approach. filedescriptor编号可以在下一次接受/连接/打开调用时重复使用,从而导致与您当前的方法不一致。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM