Page 1 of 1

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

Posted: Thu Nov 24, 2016 1:32 pm
by davdav
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.

Re: question on "read" function (lwip_read)

Posted: Thu Nov 24, 2016 5:04 pm
by kolban
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

Re: question on "read" function (lwip_read)

Posted: Thu Nov 24, 2016 9:42 pm
by ESP_Angus
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.

Re: question on "read" function (lwip_read)

Posted: Fri Nov 25, 2016 8:25 am
by davdav
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.

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

Posted: Mon Nov 28, 2016 8:14 am
by davdav
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);