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.