Dear community
In an attempt to implement an LTE TCP client, I'm stuck at the problem, that `recv()` doesn't return after the server has closed the connection.
My test implementation does a simple http request (source code attached at the end of the message):
- Connect to a web server
- Send "GET / HTTP/1.0\r\n\r\n"
- Shutdown (SHUT_WR)
- Receive while return value of `recv()` > 0.
- Close
It does everything nicely except it never arrives at stage 5.
According to https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html I would expect it to return '0' after the server has shut down the connection.
Any suggestions on what could be the problem here would be greatly appreciated!
Environment:
-- Zephyr version: 2.3.0-rc1
-- Board: nrf9160dk_nrf9160
-- West version: 0.7.2
-- DTC version: 1.4.7
-- Toolchain: gcc-arm-none-eabi-7-2018q2
Code used for testing:
int test_tcp(void) { int ret = -1; int fd = -1; struct addrinfo *addr_res; char recv_buf[10]; /** * Init modem & link control */ ret = at_cmd_write("AT+CMEE=1", NULL, 0, NULL); if (ret != 0) { printk("at_cmd_write(AT+CMEE=1) failed with %d\n", ret); return 0; } ret = lte_lc_init(); if (ret != 0) { printk("lte_lc_init() failed with %d\n", ret); return 0; } /** * Connect to LTE network */ ret = lte_lc_connect(); if (ret != 0) { printk("lte_lc_connect() failed with %d\n", ret); return 0; } printk("--------- LTE CONNECTED ---------\n"); /** * Connect to TCP host */ struct addrinfo hints = {.ai_family = AF_INET, .ai_socktype = SOCK_STREAM}; ret = getaddrinfo("petstore.swagger.io", NULL, &hints, &addr_res); if(ret != 0) { printk("getaddrinfo() failed with %d\n", errno); return 0; } ((struct sockaddr_in*)addr_res->ai_addr)->sin_port = htons(80); fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd < 0) { printk("socket() failed with %d\n", errno); return 0; } ret = connect(fd, addr_res->ai_addr, sizeof(struct sockaddr_in)); if (ret < 0) { printk("connect() failed with %d\n", errno); return 0; } else { printk("--------- TCP CONNECTED ---------\n"); } char *query = "GET / HTTP/1.0\r\n\r\n"; ret = send(fd, query, strlen(query), 0); if (ret < 0) { printk("send() failed with %d\n", errno); return 0; } ret = shutdown(fd, SHUT_WR); if (ret < 0) { printk("shutdown() failed with %d\n", errno); return 0; } printk("--------- START RECEIVING ---------\n"); do { ret = recv(fd, recv_buf, sizeof(recv_buf-1), 0); if (ret > 0) { recv_buf[ret] = '\0'; printk("%s", recv_buf); } } while (ret > 0); if (ret < 0) { printk("recv() failed with %d\n", errno); return 0; } printk("--------- END RECEIVING ---------\n"); close(fd); return 0; }
Output:
*** Booting Zephyr OS build v2.3.0-rc1-ncs1 ***
+CEREG: 2,"9D08","013A2305",7,0,0,"11100000","11100000"
+CEREG: 5,"9D08","013A2305",7,,,"11100000","11100000"
--------- LTE CONNECTED ---------
--------- TCP CONNECTED ---------
--------- START RECEIVING ---------
HTTP/1.1 302 Moved Temporarily
Server: awselb/2.0
Date: Fri, 07 Aug 2020 17:31:50 GMT
Content-Type: text/html
Content-Length: 126
Connection: close
Location: prod-swagger-oss-1833484297.us-east-1.elb.amazonaws.com:443/
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
</body>
</html>