read () в al oop с неблокирующим сокетом читает только первые 1024 байта - PullRequest
1 голос
/ 05 февраля 2020

Следующий код в socketRead() отправляет 32 Кбайт данных. Однако считываются только первые 1024 байта. Розетка неблокирующая. Неправильно ли я использую EWOULDBLOCK и EAGAIN?

Я бы ожидал, что код в socketRead() будет продолжать циклическое чтение всего 32 Кбайт вместо остановки после считывания только 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;
}

1 Ответ

1 голос
/ 07 февраля 2020

Спасибо всем комментариям. Следующий код теперь работает правильно. Возможно, потребуется немного доработать, но это по крайней мере работает.

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;
}
...