English 中文(简体)
甲型六氯环己烷与甲型六氯环己烷的关联在试验服务器中失败
原标题:Linux TCP connect with Select() fails at testserver

My problem is the following: I m programming an Interface in Linux to control a GPIB Controller via Ethernet. To do so I open a TCP socket and just send the commands to the Controller. This is working fine so far. The problem I have occured at writing some kind of unit test for my Interface: To check I am using a tcp acceptor from boost lib in a seperate thread and just connect to it instead of the actual controller. This is working too, but only as long as the connect() call from the interface is blocking. However since I need a specified timeout for the connect() call I had to connect with the select() function:

    // Open TCP Socket
    m_Socket = socket(PF_INET,SOCK_STREAM,0);
    if( m_Socket < 0 )
    {
        m_connectionStatus = STATUS_CLOSED;
        return ERR_NET_SOCKET;
    }

    struct sockaddr_in addr;
    inet_aton(m_Host.c_str(), &addr.sin_addr);
    addr.sin_port = htons(m_Port);
    addr.sin_family = PF_INET;

    // Set timeout values for socket
    struct timeval timeouts;
    timeouts.tv_sec = SOCKET_TIMEOUT_SEC ;   // const -> 5
    timeouts.tv_usec = SOCKET_TIMEOUT_USEC ; // const -> 0
    uint8_t optlen = sizeof(timeouts);

    if( setsockopt( m_Socket, SOL_SOCKET, SO_RCVTIMEO,&timeouts,(socklen_t)optlen) < 0 )
    {
        m_connectionStatus = STATUS_CLOSED;
        return ERR_NET_SOCKET;
    }

    // Set the Socket to TCP Nodelay ( Send immediatly after a send / write command )
    int flag_TCP_nodelay = 1;
    if ( (setsockopt( m_Socket, IPPROTO_TCP, TCP_NODELAY,
            (char *)&flag_TCP_nodelay, sizeof(flag_TCP_nodelay))) < 0)
    {
        m_connectionStatus = STATUS_CLOSED;
        return ERR_NET_SOCKET;
    }
    // Save Socket Flags
    int opts_blocking = fcntl(m_Socket, F_GETFL);
    if ( opts_blocking < 0 )
    {
        return ERR_NET_SOCKET;
    }
    int opts_noblocking = (opts_blocking | O_NONBLOCK);
    // Set Socket to Non-Blocking
    if (fcntl(m_Socket, F_SETFL, opts_noblocking)<0)
    {
        return ERR_NET_SOCKET;
    }
    // Connect
    if ( connect(m_Socket, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        // EINPROGRESS always appears on Non Blocking connect
        if ( errno != EINPROGRESS )
        {
            m_connectionStatus = STATUS_CLOSED;
            return ERR_NET_SOCKET;
        }
        // Create a set of sockets for select
        fd_set socks;
        FD_ZERO(&socks);
        FD_SET(m_Socket,&socks);
        // Wait for connection or timeout
        int fdcnt = select(m_Socket+1,NULL,&socks,NULL,&timeouts);
        if ( fdcnt < 0 )
        {
            return ERR_NET_SOCKET;
        }
        else if ( fdcnt == 0 )
        {
            return ERR_TIMEOUT;
        }
    }
    //Set Socket to Blocking again
    if(fcntl(m_Socket,F_SETFL,opts_blocking)<0)
    {
        return ERR_NET_SOCKET;
    }

    m_connectionStatus = STATUS_OPEN;
    return x2e::OK;

If I use this function I can still connect on the real controller and communicate with it. But if I use my testserver I just can t connect, select just leaves with a return value of 0. So now someone may say that my testserver just doesn t work....but If I use a blocking connect() call I can send to my testserver without any problems... Maybe someone has an idea what I could do...?

最佳回答

with nonblocking socket connect() call may return 0 with the connection is still not ready the connect() code section, may be written like this(my connect wraper code segment learnt from the python implementation):

    if (FAIL_CHECK(connect(sock, (struct sockaddr *) &channel, sizeof(channel)) &&
            errno != EINPROGRESS))
    {
        gko_log(WARNING, "connect error");
        ret = HOST_DOWN_FAIL;
        goto CONNECT_END;
    }

    /** Wait for write bit to be set **/
#if HAVE_POLL
    {
        struct pollfd pollfd;

        pollfd.fd = sock;
        pollfd.events = POLLOUT;

        /* send_sec is in seconds, timeout in ms */
        select_ret = poll(&pollfd, 1, (int)(send_sec * 1000 + 1));
    }
#else
    {
        FD_ZERO(&wset);
        FD_SET(sock, &wset);
        select_ret = select(sock + 1, 0, &wset, 0, &send_timeout);
    }
#endif /* HAVE_POLL */
    if (select_ret < 0)
    {
        gko_log(FATAL, "select/poll error on connect");
        ret = HOST_DOWN_FAIL;
        goto CONNECT_END;
    }
    if (!select_ret)
    {
        gko_log(FATAL, "connect timeout on connect");
        ret = HOST_DOWN_FAIL;
        goto CONNECT_END;
    }

缩略语

res = connect(s->sock_fd, addr, addrlen);
if (s->sock_timeout > 0.0) {
    if (res < 0 && errno == EINPROGRESS && IS_SELECTABLE(s)) {
        timeout = internal_select(s, 1);
        if (timeout == 0) {
            /* Bug #1019808: in case of an EINPROGRESS,
               use getsockopt(SO_ERROR) to get the real
               error. */
            socklen_t res_size = sizeof res;
            (void)getsockopt(s->sock_fd, SOL_SOCKET,
                             SO_ERROR, &res, &res_size);
            if (res == EISCONN)
                res = 0;
            errno = res;
        }
        else if (timeout == -1) {
            res = errno;            /* had error */
        }
        else
            res = EWOULDBLOCK;                      /* timed out */
    }
}

if (res < 0)
    res = errno;
问题回答

暂无回答




相关问题
Signed executables under Linux

For security reasons, it is desirable to check the integrity of code before execution, avoiding tampered software by an attacker. So, my question is How to sign executable code and run only trusted ...

encoding of file shell script

How can I check the file encoding in a shell script? I need to know if a file is encoded in utf-8 or iso-8859-1. Thanks

How to write a Remote DataModule to run on a linux server?

i would like to know if there are any solution to do this. Does anyone? The big picture: I want to access data over the web, using my delphi thin clients. But i´would like to keep my server/service ...

How can I use exit codes to run shell scripts sequentially?

Since cruise control is full of bugs that have wasted my entire week, I have decided the existing shell scripts I have are simpler and thus better. Here is what I have so far svn update /var/www/...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

热门标签