Solaris上的C套接字选择错误

时间:2016-08-24 16:28:18

标签: c sockets solaris

我在套接字选择上得到-1的返回值。但是,只有在我们使用新安装的sybase数据库时才会发生这种情况。将此代码与旧数据库一起使用,我没有得到任何套接字选择错误,一切正常。

在下面的示例中,how_many = 2,timeout_secs = 60。

重要的是要注意,在下面的代码中,当它工作时,file_limits.rlim_cur是256.但是新数据库file_limits.rlim_cur =超过65,000并且套接字选择返回-1。我已经尝试将select中的第一个参数硬编码为256,但它仍然返回-1。

int socket_activity( int how_many, int *fd, int timeout_secs )
{
int                                 i;
int                                 select_fd;
fd_set                              read_fds;
fd_set                              except_fds;
struct timeval              timeout;
struct rlimit               file_limits;

/*
** Determine the current limits.
*/

if ( getrlimit( RLIMIT_NOFILE, &file_limits ) != 0 )
    return( -1 );

/*
** Set up the select structures.  Initialize the timeout to the specified
** seconds.  Only non-negative file descriptors are initialized.
*/

FD_ZERO( &read_fds );
FD_ZERO( &except_fds );
for ( i = 0; i < how_many; i++ )

    if ( fd[i] >= 0 ) {

        FD_SET( fd[i], &read_fds );
        FD_SET( fd[i], &except_fds );

    }  /*  of if  */

timeout.tv_sec  = timeout_secs;
timeout.tv_usec = 0;

/*
** Perform the select and check on the results.
*/

select_fd = select( file_limits.rlim_cur,
                    &read_fds,
                    NULL,
                    &except_fds,
                    &timeout );

if ( select_fd > 0 ) {

    /*
    ** Scan the list of file descriptors and return which file
    ** descripitor show activity.  Only check non-negative file descriptors.
    */

    for ( i = 0; i < how_many; i++ )
        if ( ( fd[i] >= 0 ) &&
             ( FD_ISSET( fd[i], &read_fds ) ) )
            return( fd[i] );

    /*
    ** No file descriptor showed activity so return zero to indicate
    ** that a timeout occured.
    */

    return( 0 );

}  /*  of if  */

else

    /*
    ** Simply return the return value from select (the function will
    ** return a 0 on timeout or a -1 on error).
    */

    return( select_fd );

}  /*  of function  */

1 个答案:

答案 0 :(得分:0)

你真的需要post an MCVE来获得真正的帮助。由于这一点,这是更明智的推测而不是实际的答案。

首先,假设您已经通过指向int *打开文件描述符数组的int,这是没用的:

/*
** Determine the current limits.
*/

if ( getrlimit( RLIMIT_NOFILE, &file_limits ) != 0 )
    return( -1 );

如果您已经通过已经打开的文件描述符,那么打开描述符数量的资源限制是完全无关紧要的 - 描述符已经打开,如果某些内容是降低限制,你可能无法对某些描述符采取行动。

其次,如果打开文件的限制大于FD_SETSIZE中的值,则会出现问题。您传递给选择的数组 - read_fdsexcept_fds - 每个都包含最多FD_SETSIZE个元素:

select_fd = select( file_limits.rlim_cur,
                    &read_fds,
                    NULL,
                    &except_fds,
                    &timeout );

我不知道Solaris安装中的FD_SETSIZE是什么,但是如果您发布了以下代码,那么下面的代码file_limits.rlim_cur256&#34 ;在这个问题上,我强烈怀疑这是怎么回事。鉴于Solaris select(3C) man page的内容是

  

<强>错误

     

如果出现select()pselect()函数将失败:

     

...

     

EINVAL nfds参数小于0或大于FD_SETSIZE

您需要修复代码。

这将导致数组中稍后描述符的饥饿:

for ( i = 0; i < how_many; i++ )
    if ( ( fd[i] >= 0 ) &&
         ( FD_ISSET( fd[i], &read_fds ) ) )
        return( fd[i] );

您始终返回包含您找到的活动的第一个描述符。如果数组中的第一个总是忙,那么它就是唯一一个得到服务的人。

你也忽略了except_fds。如果一个人变坏了#34;在这种情况下,没有其他描述符将具有可读数据,您的代码将停止执​​行除select()中的循环之外的任何操作。