我在多线程环境下使用winsock,程序在正常运行一段时间后,发生连接超时错误,接着所有的连接都超时,并且操作系统网络连接好像断掉,其他运行的下载程序停止,将我的程序中断,其他下载程序恢复正常。我使用阻塞和非阻塞模式都一样。
可能是什么原因?
谢谢!

解决方案 »

  1.   

    是否用过的socket句柄没有关闭释放,造成文件描述字用光了
      

  2.   

    如果文件描述字用完,创建SOCKET时会出错的,但是我的程序没有,因此应该不是文件描述字用完。
      

  3.   

    多个线程都在不间断的连接不同的主机,然后发生连接超时,显然没有死锁。另外,我用一个线程依次连接不同主机时,程序运行到某个时候,也发生和多线程类似的问题。以下是我的程序连接代码:void PlainSocketImpl::connectToAddress(InetAddress pAddress,
                                           int port, size_t timeoutMS)
    {//
    // create and initialize a sockaddr_in structure
    // specifying the requested port.
    //
    struct sockaddr_in sa;
    ::memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(port); // convert port to network byte order 
    ::memcpy(&sa.sin_addr, pAddress.getAddress(), pAddress.getAddressLength());//
    // If a timeout value has been specified, then we need to set the socket
    // non-blocking
    //
    bool oldBlocking = m_bBlocking;
    if(timeoutMS != 0)
    {
    setBlocking(false);
    }//
    // Call ::connect() to create the socket connection.
    // ::connect() will return zero is successful, otherwise -1.
    //
    // The WIN32 documentation recommends comparing the return value
    // against the manifest constant SOCKET_ERROR, but as this is not 
    // mandatory, we will use the portable test of < 0.
    //
    if(::connect(m_rpSocketDescriptor->getFD(), reinterpret_cast<struct sockaddr*>(&sa), sizeof(struct sockaddr_in)) < 0)
    {
    int errorNum = NetUtils::GetLastSocketError();
    bool bConnected = false; //
    // If we have set the socket non-blocking (due to a timeout being specified)
    // then we can expect the connect() to fail with EINPROGRESS.  In this case
    // we must perform a select() to wait for the command's completion.
    //
    if(!m_bBlocking && errorNum == EINPROGRESS)
    {
    // select for readability or writability
    if(NetUtils::SelectSocket(m_rpSocketDescriptor, timeoutMS, true, true))
    {
    //
    // The select succeeded, but this may be due to an error 
    // on the socket.  This can be established using ::getsockopt
    // (there are other ways, but this is the Stevens method)
    //
    // Note: for Solaris portability reasons, we do not call
    // getIntOption, but call getsockopt directly
    //
    int error = 0;
    cel_socklen_t retLen = sizeof(error); if(::getsockopt(m_rpSocketDescriptor->getFD(), SOL_SOCKET, SO_ERROR, (char*)&error, &retLen) < 0)
    {
    error = errno;
    }

    if(error)
    {
    // If an error has occured then we treat it the same way whether or
    // not there is a timeout value.  For this reason we just set the
    // errorNum and allow the code to fall-through to the next section
    // where an appropriate exception is thrown. errorNum = error;
    }
    else
    {
    // Great!  The select() succeeded and the socket has no error
    // condition, this means that it is now connected okay.
    bConnected = true;
    }
    }
    else
    {
    static const String err(_T("Connection timed out"));
    throw SocketTimeoutException(err);
    }
    }

    if(!bConnected)
    {
    // ... and throw an appropriate exception
    String errMsg = NetUtils::GetSocketErrorString(errorNum);
    errMsg += _T(" for: ");
    errMsg += pAddress.getHostName(); if(errorNum == ENETUNREACH || errorNum == EHOSTUNREACH)
    {
    throw NoRouteToHostException(errMsg);
    }
    else
    {
    throw ConnectException(errMsg);
    }
    }
    }