select()在从socket读取时返回-1

时间:2014-10-08 10:31:51

标签: c++ sockets visual-c++

我正在尝试使用select()解决套接字超时问题的读取问题。不幸的是,此函数在被调用后立即返回-1。什么可能是错的?

commStatus communicate( const char * tx, char * rx, const int bufSize , const char * inetAddr, const int port )
{

    commStatus r;
    if (!sockInitialised) initSock();

    if (sockInitialised)
    {
        SOCKET s;
        struct sockaddr_in server;

        server.sin_addr.s_addr = inet_addr(inetAddr);
        server.sin_family = AF_INET;
        server.sin_port = htons( port );

        if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
        {
            std:stringstream d; d <<"Could not create socket : " << WSAGetLastError();
            LogIt(d,Level::Error);
        } else
        {
            if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
            {
                puts("connect error");
                r= commStatus::COMM_NO_TRANSMIT ;
            } else
            {
                int l =strlen(tx)+strlen("DATA ");

                char* dtx ;
                dtx = (char*) calloc(sizeof(char),strlen(tx)+strlen("DATA ") + 1 );

                sprintf(dtx,"DATA %s",tx);

                if( send(s , dtx , strlen(dtx) , 0) < 0)
                {
                    puts("Send failed");
                    r= commStatus::COMM_NO_TRANSMIT;
                } else
                {

                    int recv_size = 0;


                    struct timeval selTimeout;
                    selTimeout.tv_sec = 20;       /* timeout (secs.) */
                    selTimeout.tv_usec = 0;            /* 0 microseconds */
                    fd_set readSet;
                    FD_ZERO(&readSet);
                     #define STDIN_FILENO 0
                    FD_SET(STDIN_FILENO, &readSet);//stdin manually trigger reading
                    FD_SET(s, &readSet);//tcp socket
                    int numReady = select(s+1, &readSet, NULL, NULL, &selTimeout);


                    if(numReady > 0)
                    {
                        if((recv_size = recv(s , rx , bufSize ,0)) == SOCKET_ERROR)
                        {
                            r= commStatus::COMM_NO_RECEIVE;
                        } else
                        {
                            rx[recv_size] = '\0';
                            r= commStatus::COMM_OK;
                        }
                    } else r=commStatus::COMM_NO_RECEIVE;
                }
                free(dtx);
            }
        }
    } else r= commStatus::COMM_NO_TRANSMIT;
return r;

}

2 个答案:

答案 0 :(得分:0)

在C下,您可以检查errno变量,它应该告诉您导致错误的特定问题。

或者,您可能拥有perror()函数,该函数将为您提供可读的版本:

#include <stdio.h>
:
perror ("select");

如果你在 Windows下, WSAGetLastError()将作为errno变量,this page提供可能性和解释:

WSANOTINITIALISED - 在使用此功能之前,必须成功进行WSAStartup调用。

WSAEFAULT - Windows套接字实现无法为其内部操作分配所需的资源,或者readfds,writefds,exceptfds或timeval参数不属于用户地址空间。

WSAENETDOWN - 网络子系统发生故障。

WSAEINVAL - 超时值无效,或者所有三个描述符参数均为空。

WSAEINTR - 通过WSACancelBlockingCall取消阻止Windows Socket 1.1调用。

WSAEINPROGRESS - 正在阻止Windows Sockets 1.1调用,或者服务提供商仍在处理回调函数。

WSAENOTSOCK - 其中一个描述符集包含一个不是套接字的条目。

答案 1 :(得分:0)

据我所知,您正试图将stdin传递给Winsock的select()函数。

不幸的是,在Windows下,select()只接受套接字句柄,而不是通用文件描述符。

如果你打电话给WSAGetLastError(),你可能会看到它返回WSAENOTSOCK