简体   繁体   中英

Is ioctl()'s FIONREAD on a C socket reliable?

I'm seeing strange behavior with the following piece of code:

int len;
ioctl(conn_fd, FIONREAD, &len);

The usual code you might imagine precedes this (it's a toy web server):

...
int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
listen(sock_fd, 5);
int conn_fd = accept(sock_fd, (struct sockaddr *) &client_addr, &client_addr_size);

The unusual behavior is when I use curl to make a request to my toy web server, everything works perfect and len is the exact size of the request. When I use Chrome, Postman, or wget, len is 0. Because len is 0, my code treats it as an empty response and doesn't consume the request.

To verify there is actually data (besides the fact that curl works), I follow the code up with:

char full_request[16384];
int bytes_read = read(conn_fd, full_request, 16383);

To my delight, outputting full_request gives me, well, the full request no matter if it's curl, Chrome, Postman, or wget.

What gives? Is my call to ioctl not to be trusted? Is there a better way to know the size of the data coming in so I can consume it?

EDIT for EJP:

 char *full_request = malloc(1 * sizeof(char));
 *full_request = '\0';

 for (;;) {
     char buf[64];
     int bytes_read;
     int new_len;

     bytes_read = recv(conn_fd, buf, 63, 0);
     buf[bytes_read] = '\0';

     if (bytes_read <= 0) break;

     new_len = strlen(full_request) + bytes_read + 1;

     full_request = realloc(full_request, new_len * sizeof(char));
     strcat(full_request, buf);
 }

The problem with your reasoning is that read() blocks until data is available, or end of stream or an error occurs. So the fact that it did return data doesn't indicate that FIONREAD was wrong at the moment you called it. There is rarely a good reason to use FIONREAD.

You also cannot rely on a single read returning the full request. It is only obliged to transfer at least one byte. You have to loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM