Non-blocking sockets, select() and transmit buffer size

permal
Posts: 384
Joined: Sun May 14, 2017 5:36 pm

Non-blocking sockets, select() and transmit buffer size

Postby permal » Sat Jul 08, 2017 7:36 am

Hi,

I'm working on an implementation using non-blocking sockets via select(). As it is not possible to change the transmit buffer size via SO_SNDBUF socket option (only SO_RCVBUFF can be enabled in menuconfig), am I correct to assume that the option CONFIG_TCP_SND_BUF_DEFAULT (under lwip/tcp) always correctly reflects the amount of bytes that a send() will accept when FD_ISSET(sock, &write_set) returns true after a call to select() ? Does this also apply to sockets created using SOCK_DGRAM?

Secondly, the option is named nn_DEFAULT; what is a non-default value and how would that be set since SO_SNDBUF is non-functional?

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

Re: Non-blocking sockets, select() and transmit buffer size

Postby ESP_Angus » Mon Jul 10, 2017 3:11 am

Hi permal,
permal wrote:As it is not possible to change the transmit buffer size via SO_SNDBUF socket option (only SO_RCVBUFF can be enabled in menuconfig), am I correct to assume that the option CONFIG_TCP_SND_BUF_DEFAULT (under lwip/tcp)
For TCP, there is a non-standard IDF extension which allows you to call call setsockopt(TCP_SNDBUF) with an int-sized parameter which is the send buffer size as a multiple of the TCP_MSS value (rather than in bytes.) ie the send buffer size in bytes is the parameter value multiplied by TCP_MSS. This lets you set per-socket send buffer sizes, which override the default TCP send buffer size value which is set via CONFIG_TCP_SND_BUF_DEFAULT.
always correctly reflects the amount of bytes that a send() will accept when FD_ISSET(sock, &write_set) returns true after a call to select() ?
POSIX select() doesn't make any great guarantees in this department, only that the socket will accept "some" bytes. For TCP send(), the guarantee you have is that if FD_ISSET(sock, &write_set) is true then the result of send(sock, something, somelen) will be at least 1, but you can always be left with bytes to send the next time around.
Does this also apply to sockets created using SOCK_DGRAM?
For UDP, sendto() will try to allocate a packet buffer to hold the full UDP packet of the size requested (up to 64KB) and will return with errno=ENOMEM if this fails. Otherwise, provided FD_ISSET(sock, &write_set) is set then the sendto() will succeed. But you should check for this failure. Generally if the ESP32 is not low on free memory then you won't see ENOMEM here.

permal
Posts: 384
Joined: Sun May 14, 2017 5:36 pm

Re: Non-blocking sockets, select() and transmit buffer size

Postby permal » Mon Jul 10, 2017 6:05 pm

Great answer. Thanks!

Jami17
Posts: 20
Joined: Wed Jul 12, 2017 10:55 pm

Re: Non-blocking sockets, select() and transmit buffer size

Postby Jami17 » Tue Nov 03, 2020 6:29 pm

For TCP, there is a non-standard IDF extension which allows you to call call setsockopt(TCP_SNDBUF) with an int-sized parameter which is the send buffer size as a multiple of the TCP_MSS value (rather than in bytes.) ie the send buffer size in bytes is the parameter value multiplied by TCP_MSS. This lets you set per-socket send buffer sizes, which override the default TCP send buffer size value which is set via CONFIG_TCP_SND_BUF_DEFAULT.

With the current IDF version TCP_SNDBUF isn't found by the compiler anymore, and looking into sockets.c I don't find anything either.

Has it been replaced by a different constant or has the entire functionality been removed?

Who is online

Users browsing this forum: bushpulbek and 90 guests