[SOLVED] question on "read" function (lwip_read)

davdav
Posts: 208
Joined: Thu Nov 17, 2016 2:33 pm

[SOLVED] question on "read" function (lwip_read)

Postby davdav » Thu Nov 24, 2016 1:32 pm

Hi everybody,

I have a question about "read" (lwip_read) function. I have to connect to a server and I leave the connection permanently open.

When connection is estabilished I send a presentation to server and wait for some data (indefinitely). What I checked is that when I call the function

Code: Select all

r = read(s, recv_buf, sizeof(recv_buf)-1);
the task stop until the server send some data.


I guess that when I call the function if there are no data to read, it should return r=0 and go ahead. Instead I check that it waits for incoming data.

Is it how it should work? I can cope with this behaviour but I have experience with other module (typically GSM/GPRS) where an "interrupt" (event) is called to inform me that some data are ready to be read.


Thank you.
Last edited by davdav on Mon Nov 28, 2016 9:29 am, edited 1 time in total.

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: question on "read" function (lwip_read)

Postby kolban » Thu Nov 24, 2016 5:04 pm

If you call read() and there is no data available, then the default sematics are indeed to block until data does become available. If what you want to do is to return immediately if there is no data, instead of using read() use recv() with the option "MSG_DONTWAIT". This will cause the return to happen straight away if there is no data available. There are other options ... such as setting a socket non blocking. You might want to do some study on generic "sockets APIs" as these seem all applicable to the ESP32 story.

See also:

http://man7.org/linux/man-pages/man2/recv.2.html
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: question on "read" function (lwip_read)

Postby ESP_Angus » Thu Nov 24, 2016 9:42 pm

In addition to kolban's suggestion, the other option is to use "select" which allows you to specify a list of socket file descriptors, and an optional timeout. select returns when one or all of the sockets has data, or after the timeout.

We don't have an example of socket select() in esp-idf right now, but LWIP's contrib repo has one:
https://github.com/goertzenator/lwip/bl ... les.c#L117

Or you can read up on select() for BSD sockets in other contexts - Linux programming, man pages, books, etc. It works the same in esp-idf.

davdav
Posts: 208
Joined: Thu Nov 17, 2016 2:33 pm

Re: question on "read" function (lwip_read)

Postby davdav » Fri Nov 25, 2016 8:25 am

Thank you kolban and ESP_Angus.

I will read and study your suggestion because in effect the "read" function is not the right choice for my application.

I let the ESP32 connected all night long to the server (without giving any command) and this morning when I try to transfer some data from server to ESP32, it didn't receive any message. In practice the server disconnected the ESP32 (maybe because there isn't a keepalive signal?) but the ESP32 seems to be blocked at "read" function and can't exit from it. The ESP32 is however correclty connected to wifi network and it is able to open another socket in another task.

I will modify my code and try to solve the issue.

Thanks.

davdav
Posts: 208
Joined: Thu Nov 17, 2016 2:33 pm

[Solved] question on "read" function (lwip_read)

Postby davdav » Mon Nov 28, 2016 8:14 am

I have modified my code using the "select" function and it seems to work. I report a snipset of the code I used, in case someone need to have a connection without closing the channel with the server..

Code: Select all

    int s, r;
    char recv_buf[64];

    fd_set read_push_set;
    struct timeval tv;
    int retval;

//..connect to server...

do {
	// Initialize the set of active sockets
	FD_ZERO (&read_push_set);
	FD_SET (s, &read_push_set);

	//timoeut of 15 seconds
	tv.tv_sec = 15;
	tv.tv_usec = 0;

	// Block until input arrives on one or more active sockets.
	retval = select (FD_SETSIZE, &read_push_set, NULL, NULL, &tv);

	//some data received from server
	if (retval)
	{
		// Read response
		bzero(recv_buf, sizeof(recv_buf));

		r = read(s, recv_buf, sizeof(recv_buf)-1);

		//Do something with data received...
	}
	// Error calling function "select"
	else if (retval == -1)
	{
		//close socket and exit
		close(s);
		break;
	}
	else
	{
		//Do something in case "select" timeout expired...
	}

}while (r > 0);

Who is online

Users browsing this forum: ghmyers, Google [Bot] and 65 guests