下载 FreeRTOS
 

出色的 RTOS & 嵌入式软件

最新资讯
简化任何设备的身份验证云连接。
利用 CoAP 设计节能型云连接 IoT 解决方案。
11.0.0 版 FreeRTOS 内核简介:
FreeRTOS 路线图和代码贡献流程。
使用 FreeRTOS 实现 OPC-UA over TSN。

FreeRTOS_sendto()

[FreeRTOS-Plus-TCP API 引用]

FreeRTOS_sockets.h
int32_t FreeRTOS_sendto( Socket_t xSocket,
                         const void *pvBuffer,
                         size_t xTotalDataLength,
                         uint32_t ulFlags,
                         const struct freertos_sockaddr *pxDestinationAddress,
                         socklen_t xDestinationAddressLength );
		

发送数据至 UDP 套接字(请参阅 FreeRTOS_send(), 了解 TCP 等效项)。 套接字必须已通过 成功调用 FreeRTOS_socket() 创建。

此函数可以与标准调用语义或零拷贝 调用语义:

  • 标准 sendto() 语义

    数据从 pvBuffer 参数指向的地址复制到 TCP/IP 堆栈内部分配的网络缓冲区。

    当 ulFlags 参数不存在 FREERTOS_ZERO_COPY 位组时,使用标准 sendto() 语义。 请参阅此页面底部的示例和本网站上提供的其他应用程序 示例。

  • 零拷贝 sendto() 语义

    应用程序编写者:

    1. 从 TCP/IP 堆栈获取缓冲区。
    2. 将待发送数据写入 从 TCP/IP 堆栈获得的缓冲区。
    3. 将指向(已完成的)缓冲区的指针用作 pvBuffer 参数。

    然后,TCP/IP 堆栈会通过 TCP/IP 堆栈将对同一缓冲区的引用传递给以太网驱动器,并在那进行传输 (通常在硬件允许的情况下通过 DMA 传输)。

    当 ulFlags 参数存在 FREERTOS_ZERO_COPY 位组时,使用零拷贝 sendto() 语义。 请参阅 本页底部的示例以及 本网站上提供的其他应用程序示例。

FreeRTOS_sendto() 具有可选超时。 该超时默认为 ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME, 可使用 FreeRTOS_setsockopt() 进行修改。 如果发送操作不能立即排队发送字节,那么 调用 RTOS 任务将被保持在阻塞状态(以执行其他任务 ),直至可排队发送字节,或 超时到期。 以下情况会发生超时:

  • 使用标准 sendto() 语义,且 TCP/IP 堆栈 无法及时获取网络缓冲区。 或,
  • 队列中无可用空间向 IP RTOS 任务发送消息(请参阅 FreeRTOSIPConfig.h 头文件中的 ipconfigEVENT_QUEUE_LENGTH 设置)。

如果 FreeRTOS_sendto() 在一个套接字上被调用, 且该套接字未绑定到一个移植 号,且 ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 值 在 FreeRTOSIPConfig.h 中设置为 1,则 TCP/IP 堆栈会自动将该套接字 与私有地址范围中的一个移植号绑定。

FreeRTOS -Plus- TCP [当前]未使用所有函数参数。 未使用的参数保留在函数的原型中, 确保与预期的标准伯克利套接字 API 一致, 并确保与 FreeRTOS-Plus-TCP 的未来版本兼容。

参数:

xSocket   接收发送数据的套接字的句柄。 套接字 必须已被创建(请参阅 FreeRTOS_socket())。

pvBuffer   如果正在使用标准调用语义(ulFlags 参数不存在 FREERTOS_ZERO_COPY 位组), 则 pvBuffer 指向正被传输的数据 的数据源。 FreeRTOS_sendto() 将从 pvBuffer 拷贝数据至 TCP/IP 堆栈内的网络缓冲区。

如果正在使用零拷贝调用语义(ulFlags 参数存在 FREERTOS_ZERO_COPY 位组), 则 pvBuffer 指向此前从 TCP/IP 堆栈获得的缓冲区,且该缓冲区已包含正在发送的数据。 TCP/IP 堆栈会控制该缓冲区, 而非拷贝缓冲区数据。

请参阅以下示例用法内容和本网站提供的应用程序 示例。

xTotalDataLength   待发送的字节数。

ulFlags   一组影响发送操作的逐位选项。

如果 ulFlags 存在 FREERTOS_ZERO_COPY 位组, 则函数会使用零拷贝语义, 否则函数会使用标准拷贝模式语义。 请参阅上面 pvBuffer 参数的说明。

未来 FreeRTOS-Plus-TCP 版本可以实现其他位。

pxDestinationAddress   指向 freertos_sockaddr 结构体的指针, 包含目标 IP 地址和移植号( 接收被发送数据的套接字)。 请参阅以下示例。

xDestinationAddressLength   当前未使用,但应设置为 sizeof (struct freertos_sockaddr),以确保未来的 兼容性。

返回:

实际排队发送的字节数, 如果发生错误或超时,则为 0。

注意,因为 FreeRTOS 未实现 errno, 在出现错误时的行为必然与 sendto() 函数的行为不同, 后者完全符合预期的伯克利 套接字行为。

用法示例:

第一个示例使用标准调用语义向套接字发送数据(请参阅 以下另一使用零拷贝调用语义的示例)。 套接字 被作为函数参数传入,并假定已经 通过调用 FreeRTOS_socket() 创建。 如果 ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 在 FreeRTOSIPConfig.h 中未设置为 1,那么套接字也被认为已经 使用 FreeRTOS_bind() 绑定到移植号上。


/* FreeRTOS-Plus-TCP sockets include. */
#include "FreeRTOS_sockets.h"

void vStandardSendExample( Socket_t xSocket )
{
/* Note - the RTOS task stack must be big enough to hold this array!. */
uint8_t ucBuffer[ 128 ];
struct freertos_sockaddr xDestinationAddress;
int32_t iReturned;

/* Fill in the destination address and port number, which in this case is
port 1024 on IP address 192.168.0.100. */

xDestinationAddress.sin_addr = FreeRTOS_inet_addr_quick( 192, 168, 0, 100 );
xDestinationAddress.sin_port = FreeRTOS_htons( 1024 );

/* The local buffer is filled with the data to be sent, in this case it is
just filled with 0xff. */

memset( ucBuffer, 0xff, 128 );

/* Send the buffer with ulFlags set to 0, so the FREERTOS_ZERO_COPY bit
is clear. */

iReturned = FreeRTOS_sendto(
/* The socket being send to. */
xSocket,
/* The data being sent. */
ucBuffer,
/* The length of the data being sent. */
128,
/* ulFlags with the FREERTOS_ZERO_COPY bit clear. */
0,
/* Where the data is being sent. */
&xDestinationAddress,
/* Not used but should be set as shown. */
sizeof( xDestinationAddress )
);

if( iReturned == 128 )
{
/* The data was successfully queued for sending. 128 bytes will have
been copied out of ucBuffer and into a buffer inside the TCP/IP stack.
ucBuffer can be re-used now. */

}
}

Example using FreeRTOS_sendto() with the standard (as opposed to zero copy) calling semantics


第二个示例使用零拷贝调用语义向套接字发送数据(请参阅 以上另一使用标准调用语义的示例)。 套接字 被作为函数参数传入,并假定已经 通过调用 FreeRTOS_socket() 创建。 如果 ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 在 FreeRTOSIPConfig.h 中未设置为 1,那么套接字也被认为已经 使用 FreeRTOS_bind() 绑定到移植号上。


/* FreeRTOS-Plus-TCP sockets include. */
#include "FreeRTOS_sockets.h"

void vZeroCopySendExample( Socket_t xSocket )
{
struct freertos_sockaddr xDestinationAddress;
uint8_t *pucUDPPayloadBuffer;
int32_t iReturned;

/* Fill in the destination address and port number, which in this case is
port 1024 on IP address 192.168.0.100. */

xDestinationAddress.sin_addr = FreeRTOS_inet_addr_quick( 192, 168, 0, 100 );
xDestinationAddress.sin_port = FreeRTOS_htons( 1024 );

/* Obtain a buffer from the TCP/IP stack that is large enough to hold the data
being sent. Although the maximum amount of time to wait for a buffer is passed
into FreeRTOS_GetUDPPayloadBuffer() as portMAX_DELAY, the actual maximum time
will be capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS (defined in
FreeRTOSIPConfig.h) */

pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( 128,
portMAX_DELAY );
if( pucUDPPayloadBuffer != NULL )
{
/* Write the data being sent directly into the buffer obtained from the
IP stack. In this case the data is just set to 0xff. */

memset( pucUDPPayloadBuffer, 0xff, 128 );

/* Pass the buffer (by reference) into the TCP/IP stack using the zero copy
semantics. Ensure to read the remaining source code comments for information
on managing the pucUDPPayloadBuffer pointer after this call to
FreeRTOS_sendto(). */

iReturned = FreeRTOS_sendto(
/* The socket being sent to. */
xSocket,
/* The buffer that already contains the
data being sent. */

&xBufferDescriptor,
/* The length of the data being send. */
128,
/* ulFlags with the FREERTOS_ZERO_COPY bit
set. */

FREERTOS_ZERO_COPY,
/* Where the data is being sent. */
&xDestinationAddress,
/* Not used but should be set as shown. */
sizeof( xDestinationAddress )
);

if( iReturned != 0 )
{
/* The buffer pointed to by pucUDPPayloadBuffer was successfully
passed (by reference) into the TCP/IP stack and is now queued for sending.
the TCP/IP stack is responsible for returning the buffer after it has been
sent, and pucUDPPayloadBuffer can be used safely in another call to
FreeRTOS_GetUDPPayloadBuffer(). */

}
else
{
/* The buffer pointed to by pucUDPPayloadBuffer was not successfully
passed (by reference) to the TCP/IP stack. To prevent memory and network
buffer leaks the buffer must be either reused or, as in this case,
released back to the TCP/IP stack. */

FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
}
}
}

Example using FreeRTOS_sendto() with the zero copy calling semantics
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.