具有非阻塞套接字的循环中的 read() 仅读取前 1024 个字节

read() in a loop with non-blocking socket only reads first 1024 bytes

socketRead() 中的以下代码正在发送 32K 字节的数据。但是,只读取前 1024 个字节。套接字是非阻塞的。我使用 EWOULDBLOCKEAGAIN 不当吗?

我希望 socketRead() 中的代码继续循环读取整个 32K 字节,而不是在仅读取 1024 字节后停止。 我做错了什么?

    int SetSocketNonBlocking(int socketfd)
    {
            return( fcntl(socketfd, F_SETFL, fcntl(socketfd, F_GETFL, 0) | O_NONBLOCK) );
    }


    int SocketReadReady(int sockfd, unsigned int timeoutSeconds)
    {
            fd_set set;
            struct timeval timeout;
            int retCode = 0;

            FD_ZERO(&set);
            FD_SET(sockfd, &set);

            timeout.tv_sec = timeoutSeconds;
            timeout.tv_usec = 0;

            while(1)
            {
                    retCode = select(sockfd+1, &set, NULL, NULL, &timeout);
                    if( (retCode == -1) && (errno == EINTR) )
                    {
                            continue;
                    }
                    else
                    {
                            break;
                    }
            }
            return( retCode == 1 );
    }



uint8_t *SocketRead(int sockfd, int *bytesRead)
{
        int size_recv = 0;
        int total_size = 0;
        uint8_t *data = NULL;


        // initially we will provide ourselves with a 275k buffer
        // which is more than large enough for a 3" x 8" rasterized image.
        data = malloc((size_t)READ_CHUNK_SIZE * 275);


        if( data != NULL )
        {
                if( SetSocketNonBlocking(sockfd) == -1 )
                {
                        printf("Failed setting non-blocking\n");
                }
                if( SocketReadReady(sockfd, 10) )
                {
                        printf("Socket ready for read\n");
                        do
                        {
                                // TODO: We need to at some point make sure to realloc() the buffer if we have to read more than
                                // 275k of data
                                size_recv =  recv(sockfd, (void *)&data[total_size], READ_CHUNK_SIZE, MSG_DONTWAIT);
                                if( size_recv < 0 )
                                {
                                        if( errno == EWOULDBLOCK )
                                        {
                                                break;
                                        }
                                        else if( errno == EAGAIN)
                                        {
                                                continue;
                                        }
                                }
                                else if( size_recv == 0 )
                                {
                                        // connection closed
                                        printf("Connection closed\n");
                                        break;
                                }
                                else
                                {
                                        total_size += size_recv;
                                }
                        }while(1);
                }
                else
                {
                        printf("Socket timed out waiting for data to read\n");
                }
        }

        *bytesRead = total_size;
        return data;
}

感谢大家的评论。以下代码现在可以正常工作。它可能需要一些改进,但它至少有效。

uint8_t *SocketRead(int sockfd, int *bytesRead)
{
        int size_recv = 0;
        int total_size = 0;
        uint8_t *data = NULL;
​
​
        // initially we will provide ourselves with a 275k buffer
        // which is more than large enough for a 3" x 8" rasterized image.
        data = malloc((size_t)READ_CHUNK_SIZE * 275);
​
​
        if( data != NULL )
        {
                if( SetSocketNonBlocking(sockfd) == -1 )
                {
                        printf("Failed setting non-blocking\n");
                }
                if( SocketReadReady(sockfd, 10,0) )
                {
                        printf("Socket ready for read\n");
                        do
                        {
                                // TODO: We need to at some point make sure to realloc() the buffer if we have to read more than
                                // 275k of data
                                size_recv =  read(sockfd, (void *)&data[total_size], READ_CHUNK_SIZE);
                                if( size_recv < 0 )
                                {
                                        if( errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
                                        {
                                                if( SocketReadReady(sockfd,0,100) )
                                                {
                                                        continue;
                                                }
                                                else
                                                {
                                                        break;
                                                }
                                        }
                                        else
                                        {
                                                perror("Socket read:");
                                                if( data )
                                                {
                                                        free(data);
                                                        data = NULL;
                                                }
                                                break;
                                        }
                                }
                                else if( size_recv == 0 )
                                {
                                        // connection closed
                                        printf("Connection closed\n");
                                        break;
                                }
                                else
                                {
                                        total_size += size_recv;
                                }
                        }while(1);
                }
                else
                {
                        printf("Socket timed out waiting for data to read\n");
                }
        }
​
        *bytesRead = total_size;
        return data;
}