The following code in socketRead()
is being sent 32K bytes of data. However, only the first 1024 bytes are read. The socket is non-blocking. Am I using EWOULDBLOCK
and EAGAIN
improperly?
I would expect the code in socketRead()
to keep looping reading the entire 32K bytes instead of stopping after reading only 1024 bytes. What am I doing wrong?
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;
}
Thanks to all the comments. The following code works correctly now. It may need a bit of refinement, but it at least works.
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;
}