Can FreeRTOS_select() be used with TCP type sockets?
Hi
I would like to know if the function FreeRTOSselect() can be used with TCP sockets?
The example provided here:
https://www.freertos.org/FreeRTOS-Plus/FreeRTOSPlusUDP/API/select.shtml
creates the sockets as FREERTOSIPPROTO_UDP
In other words is there anyway of having a non-blocking FreeRTOSrecv? Or a blocking FreeRTOSrecv for say 1 second?
maybe using FreeRTOS_setsockopt()?
Can FreeRTOS_select() be used with TCP type sockets?
Sure you can use
FreeRTOS_select()
on TCP sockets as well.
You were looking at old documentation of the UDP-only library.
Here you find all TCP- and UDP-API calls.
Can FreeRTOS_select() be used with TCP type sockets?
In other words is there anyway of having a non-blocking FreeRTOSrecv? Or a blocking FreeRTOSrecv for say 1 second? maybe using FreeRTOS_setsockopt()?Yes you can set the maximum time that
FreeRTOS_recv()
will wait by setting the socket option FREERTOS_SO_RCVTIMEO
.
There are three different possibilities to handle multiple socket within a single task:
Method 1) Semaphores
Method 2) Socket call-backs
Method 3) Use select
What you can do is call FreeRTOS_recv()
and FreeRTOS_send()
in a non-blocking way, and let the task block in a central place, either on a semaphore, or a task-notification, or a call to select().
Method 1) Semaphores
Give the task a semaphore and anyone can wake-up your task by giving to the semaphore (xSemaphoreGive()
or xSemaphoreGiveFromISR()
).
The IP-task can also give to the semaphore if you bind a socket to that semaphore ( on reception of data, on TX space available, on disconnect etc. )
Define in FreeRTOSIPConfig.h:
~~~
#define ipconfigSOCKETHASUSER_SEMAPHORE 1
~~~
and bind the semaphore to every socket owned by the task. There is a NTP-demo (Network Time Protocol) which uses a semaphore:
~~~
// Declare it
static SemaphoreHandle_t xNTPWakeupSem = NULL;
// Create it
xNTPWakeupSem = xSemaphoreCreateBinary();
// Bind it
FreeRTOS_setsockopt(
xUDPSocket,
0,
FREERTOS_SO_SET_SEMAPHORE,
( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) );
~~~
This is a UDP socket, but it works the same for TCP sockets. The IP-task will give to the semaphore for any relevant event:
- Data has arrived
- Data has been sent and TX space is available ( TCP-only )
- A connection is established ( either
accept()
orconnect()
) - A connection is broken ( or an error occurred )
/* Check sockets and messages in a non-blocking way. */
}
~~~
Method 2) Socket call-backs
DefineipconfigUSE_CALLBACKS
as 1 in FreeRTOSIPConfig.h
Now you can bind call-back ( application hooks ) to each of the sockets:
~~~
FREERTOSSOTCPCONNHANDLER ( 6 ) /* Install a callback for (dis) connection events. /
FREERTOS_SO_TCP_RECV_HANDLER ( 7 ) / Install a callback for receiving TCP data. /
FREERTOS_SO_TCP_SENT_HANDLER ( 8 ) / Install a callback for sending TCP data. */
FREERTOSSOUDPRECVHANDLER ( 9 ) /* Install a callback for receiving UDP data. /
FREERTOS_SO_UDP_SENT_HANDLER ( 10 ) / Install a callback for sending UDP data. */
~~~
Define a handler, e.g. on-tcp-receive
~~~
BaseTypet xOnTcpReceive( Sockett xSocket, void * pData, size_t xLength )
{
xSemaphoreGive( myTaskSemaphore );
// or
xTaskNotifyGive( myTaskHandle );
return 0; // KEEP the packet, it will be stored in the RX buffer of the socket
// FreeRTOS_recv() must be called later-on
// or
return 1; // DISCARD the packet, it will not be stored
}
F_TCP_UDP_Handler_t handler;
handler.pxOnTcpReceive = xOnTcpReceive;
FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_RECV_HANDLER,
( void * ) &handler, sizeof( handler ) );
~~~
Call-backs ( Application Hooks ) are always error-prone: it looks like user code, but in fact the code is run ( called ) from the IP-task. Thus most +TCP API’s can not be called from within the call-back.
Method 3) Use select
DefineipconfigSUPPORT_SELECT_FUNCTION
as 1 in your FreeRTOSIPConfig.h
And now you can use the select() functions. Here you find documentation.
Using select() is less flexible: you can only wake-up the task if you can access the sockets.
You could use:
~~~
#define ipconfigSUPPORT_SIGNALS 1
~~~
and interrupt a select() buy calling :
~~~
FreeRTOS_SignalSocket()
~~~
Most compatible is 3) select(), while 2) semaphore is by far the easiest.
The FTP/HTTP demo servers use a single task. It blocks in a call to select(). It can handle an unlimited number of FTP- or HTTP-clients, only limited by the amount of available RAM.
Can FreeRTOS_select() be used with TCP type sockets?
wow 🙂 thank you for the juicy info.
Can FreeRTOS_select() be used with TCP type sockets?
When using sockets and after the semaphore has been given how could I find out the reason for the Give?
I’m interested in these 3:
A connection is established ( either accept() or connect() )
A connection is broken ( or an error occurred )
Data has arrived