HTTP persistent connection with poll()
Asked Answered
R

1

0

On successfully creating the listening socket, I try to run a block of code on it that should maintain a persistent connection. Here is what I have done so far:

while(1) {
  struct pollfd pfds[1];
  pfds[0].fd = sockfd; // sockfd is my connection socket that I work on
  pfds[0].events = POLLIN;
  int num_events = poll(pfds, 1, 2000); // timeout 2 seconds
  if (num_events == 0) {
    printf("No data to read\n");
    close(sockfd);
    break;
  } else {
    // work with sockfd, recv() data from it and at the very end, do not close the connection
  }
}

I am trying to test the above code with curl. I run curl hostname:portnum hostname:portnum (2 times, consecutively) and get the following behavior: curl gets the html page that I render inside the else-block immediately and waits for 2 seconds, after that it sends the other request. The desires behavior would be so that it sent the other request RIGHT after it sends the first one.

curl -v localhost:4390 localhost:4390
*   Trying 127.0.0.1:4390...
* Connected to localhost (127.0.0.1) port 4390 (#0)
> GET / HTTP/1.1
> Host: localhost:4390
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Connection: keep-alive
< Keep-Alive: timeout=2, max=100
* no chunk, no close, no size. Assume close to signal end
< 
<html>
  Hello, world!
</html>
* Closing connection 0
* Hostname localhost was found in DNS cache
*   Trying 127.0.0.1:4390...
* Connected to localhost (127.0.0.1) port 4390 (#1)
> GET / HTTP/1.1
> Host: localhost:4390
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Connection: keep-alive
< Keep-Alive: timeout=2, max=100
* no chunk, no close, no size. Assume close to signal end
< 
<html>
  Hello, world!
</html>
* Closing connection 1

The above is what I get now from curl. The desired behavior is this.

curl -v google.com google.com
 *   Trying 142.250.203.206:80...
 * Connected to google.com (142.250.203.206) port 80 (#0)
> GET / HTTP/1.1
> Host: google.com
> User-Agent: curl/7.81.0
> Accept: */*
> 
 * Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Location: http://www.google.com/
< Content-Type: text/html; charset=UTF-8
< Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-V5HivFgCR5mSmZ20PuojOg' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
< Date: Sun, 07 Jul 2024 08:54:11 GMT
< Expires: Tue, 06 Aug 2024 08:54:11 GMT
< Cache-Control: public, max-age=2592000
< Server: gws
< Content-Length: 219
< X-XSS-Protection: 0
< X-Frame-Options: SAMEORIGIN
< 
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
 * Connection #0 to host google.com left intact
 * Found bundle for host google.com: 0x5edef1e05010 [serially]
 * Can not multiplex, even if we wanted to!
 * Re-using existing connection! (#0) with host google.com
 * Connected to google.com (142.250.203.206) port 80 (#0)
> GET / HTTP/1.1
> Host: google.com
> User-Agent: curl/7.81.0
> Accept: */*
> 
 * Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Location: http://www.google.com/
< Content-Type: text/html; charset=UTF-8
< Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-Junna8vFZULg3bC31jZ9NA' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
< Date: Sun, 07 Jul 2024 08:54:11 GMT
< Expires: Tue, 06 Aug 2024 08:54:11 GMT
< Cache-Control: public, max-age=2592000
< Server: gws
< Content-Length: 219
< X-XSS-Protection: 0
< X-Frame-Options: SAMEORIGIN
< 
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
 * Connection #0 to host google.com left intact

As you can see, Connection #0 to host google.com left intact.

Riebling answered 7/7, 2024 at 7:46 Comment(7)
if you want curl to send a request without wait, then do so. curl is external program to yours.Peptide
Curl is external program, but it works with other servers. For example, with google.com. I mean, there is no delay with that server, but there is one with mine.Riebling
how do you invoke curl commands to request your server? please update the question body.Peptide
@Peptide done, thanks for your patience.Riebling
hello, Artem. I mean, how do you type curl command in your shell. you've provided the output, the result of a command. but you miss the actual shell input.Peptide
@Peptide Of course, fixed now.Riebling
@n.m.couldbeanAI indeed, adding Content-Length helps. Thank you!Riebling
R
-2

Turns out that you have to add 'Content-Length' so that the client closes the connection once it gets every byte of data it is supposed to get.

Riebling answered 7/7, 2024 at 10:35 Comment(1)
"... so that the client closes the connection" - adding content-length is correct, but the reason given is wrong. Content-length is needed so that curl actually knows where the response has ended. Otherwise it will just wait until connection close - which it explicitly says so: "> no chunk, no close, no size. Assume close to signal end"Haema

© 2022 - 2025 — McMap. All rights reserved.