send_file 子例程

用途

通过套接字来发送文件的内容。

标准 C 库 (libc.a)

语法

#include < sys/socket.h >

ssize_t send_file(Socket_p, sf_iobuf, flags)

int * Socket_p;
struct sf_parms * sf_iobuf;
uint_t  flags;

描述

send_file 子例程通过 Socket_p 参数指向的已连接套接字发送来自 sf_iobuf 参数中指定的已打开文件的数据。

注: 目前, send_file 仅支持 TCP/IP 协议 (AF_INET 中的 SOCK_STREAM 套接字)。 在任何其他类型的套接字上使用此函数时,将返回错误。

参数

描述
Socket_p 指向要将文件发送至的套接字的套接字描述符。
注: 这与大多数套接字函数不同。
sf_iobuf 指向按如下所示定义的 sf_parms 结构:
/*
 * Structure for the send_file system call
 */
#ifdef __64BIT__
#define SF_INT64(x)     int64_t x;
#define SF_UINT64(x)    uint64_t x;
#else
#ifdef _LONG_LONG
#define SF_INT64(x)     int64_t x;
#define SF_UINT64(x)    uint64_t x;
#else
#define SF_INT64(x)     int filler_##x; int x;
#define SF_UINT64(x)    int filler_##x; uint_t x;
#endif
#endif

struct sf_parms {
    /* --------- header parms ---------- */
    void      *header_data;         /* Input/Output. Points to header buf */
    uint_t      header_length;      /* Input/Output. Length of the header */
    /* --------- file parms ------------ */
    int       file_descriptor;      /* Input. File descriptor of the file */
    SF_UINT64(file_size)            /* Output. Size of the file */
    SF_UINT64(file_offset)          /* Input/Output. Starting offset */
    SF_INT64(file_bytes)            /* Input/Output. number of bytes to send */
    /* --------- trailer parms --------- */
   void      *trailer_data;         /* Input/Output. Points to trailer buf */
   uint_t    trailer_length;        /* Input/Output. Length of the trailer */
    /* --------- return info ----------- */
    SF_UINT64(bytes_sent)           /* Output. number of bytes sent */
};
头数据
指向一个缓冲区,该缓冲区包含要在文件数据之前发送的头数据。 0 头长度 为 0 ,那么可能是 NULL 指针。 此字段将由 send_file 在传输头时进行更新-即,header_data+ 发送的头的字节数。
头长度
指定 头数据中的字节数。 0 将此字段设置为 0 ,以指示不发送头数据。 此字段将由 send_file 在传输头时进行更新-即,header_length-发送的头的字节数。
文件描述符
指定已打开的文件的文件描述符,并且该文件是可读的。 这是包含所要传输的数据的文件的描述符。 当 file_bytes = 0 时,将忽略 file_descriptor 。 此字段未由 send_file更新。
文件大小
包含由 file_descriptor指定的文件的字节大小。 此字段是由内核填充的。
文件偏移量
指定要从其开始发送数据的文件中的字节偏移量。 在传输文件数据时, send_file 将更新此字段-即,file_offset+ 发送的文件数据的字节数。
文件字节数
指定从要传输的文件中发送的字节数。 将file_bytes设置为-1会从file_offset 开始传输整个文件。 当该字段未设置为-1 时,文件数据传输时,send_file会更新该字段、file_bytes-发送的文件数据的字节数。
Trailer_data
指向一个缓冲区,该缓冲区包含要在文件数据之后发送的尾部数据。 0 Trailer_length 为 0 ,那么可能是 NULL 指针。 此字段将由 send_file 在传输尾部时进行更新-即,trailer_data+ 发送的尾部的字节数。
Trailer_length
指定 Trailer_data中的字节数。 必须将此字段设置为 0 ,以指示不发送尾部数据。 此字段将由 send_file 在传输尾部时进行更新-即,trailer_length-发送的尾部的字节数。
发送字节数
包含在此调用中实际发送到 send_file的字节数。 此字段是由内核填充的。

所有字段标记为Inputsf_parms 结构中,需要由应用程序在 send_file 调用之前进行设置。 所有字段标记为Outputsf_parms 结构中, send_file 在成功传输数据时进行调整,即指定的数据传输已部分完成或完全完成。

send_file 子例程尝试从 头数据指向的缓冲区中写入 头长度 个字节,然后从与 file_descriptor关联的文件中写入 file_bytes ,再从 Trailer_data指向的缓冲区中写入 Trailer_length 个字节,通过与 Socket_p指向的套接字关联的连接。

在发送数据时,内核会更新 sf_iobuf 指定的参数,以便在必须多次调用 send_file (由于信号中断或由于非阻塞 I/O 方式) 以完成文件数据传输时,应用程序可以重新发出 send_file 命令而不进行设置或反复重新调整这些参数。

如果应用程序设置的file_offset大于实际文件大小,或file_bytes大于(实际文件大小 - file_offset),返回值将是-1和 errno EINVAL。

标志 指定以下属性:
SF_CLOSE
在数据成功发送或排队等待传输后,关闭 Socket_p 所指向的套接字。
SF_REUSE
在成功发送数据或排队等待传输并关闭现有连接后,准备重新使用该套接字。
注: 此选项当前在此操作系统上不受支持。
SF_DONT_CACHE
未将指定的文件放入网络缓冲区高速缓存中。
SF_SYNC_CACHE
在传输之前验证/更新指定文件的网络缓冲区高速缓存。

如果设置了 SF_CLOSE 标志,那么在成功完成所请求的传输后, send_file 将断开并关闭 Socket_p 指定的已连接套接字。 Socket_p指向的套接字描述符将被设置为-1。 如果send_file返回值non-0,该标记将不起作用。

AIX 目前不支持SF_REUSE标志。 指定此标志后,Socket_p指向的套接字将被关闭,并以-1 返回。 需要为下一个连接创建一个新套接字。

send_file 将利用内核内存中的网络缓冲区高速缓存来对输出文件数据进行动态高速缓存。 对于以下文件,这将有助于提高 send_file 的性能:

  1. 重复地通过网络和
  2. 不频繁更改。

通过使用 SF_DONT_CACHE 标志,应用程序可以将指定的文件排除在高速缓存之外。 send_file 将每隔一段时间更新一次高速缓存,以确保高速缓存中的文件数据在某个时间段内有效。 可以修改 命令控制的网络选项参数 "send_file_duration" 以配置 send_file 高速缓存验证的时间间隔,缺省值为 300 (以秒为单位)。 应用程序可以使用 SF_SYNC_CACHE 标志来确保在 send_file发送指定文件之前对该文件进行高速缓存验证,而不考虑 "send_file_duration" 的值。 其他网络缓冲区高速缓存相关参数为 "nbc_limit" , nbc_max_cache "和 nbc_min_cache"。 要获取其他信息,请参阅 命令。

返回值

send_file中有三个可能的返回值:

描述
-1 发生错误,错误号包含错误代码。
0 命令已成功完成。
1 命令已部分完成,某些数据已传输,但由于某些原因 (例如,命令被信号中断) ,命令必须返回。

使用以下标记的字段:Outputsf_parms 1 0 (由 sf_iobuf指向) ,当返回值为 0 或 1 时由 send_file 更新。 字节发送 字段包含此调用中已发送的总字节数。 始终存在这样的情况: 字节发送 (Output) <= 头长度(Input)+ file_bytes (Input) + Trailer_length (Input).

send_file 支持块 I/O 方式和非块 I/O 方式。 在阻塞 I/O 方式下, send_file 将阻塞到发送所有文件数据 (以及头和尾部) 为止。 它会调整 sf_iobuf 以反映传输结果, 0 返回 0。 在完全完成请求之前, send_file 可能被中断,在这种情况下,它会调整 sf_iobuf 以反映传输进度,并返回 1。

在非阻塞 I/O 方式下, send_file 在套接字空间允许的范围内进行传输,调整 sf_iobuf 以反映传输进度,并 1 0 或 1。 当系统中没有套接字空间来缓冲任何数据时,send_file返回-1并将 errno 设置为 EWOULDBLOCK。 可以使用 选择轮询 来确定何时可以发送更多数据。

可能返回了错误号:
EBADF 套接字或文件描述符参数是无效的。
ENOTSOCK socket 参数引用的是文件,而不是套接字。
EPROTONOSUSUPPORT 协议不受支持。
EfaulT HeaderTailer 参数中指定的地址不在用户地址空间的可写部分中。
EINTR 在发送任何数据之前,该操作被信号中断。 (如果发送了某些数据, send_file 将返回在信号之前发送的字节数,并且未设置 EINTR)。
EINVAL 偏移量、HeaderTrailer,长度或标志参数无效。
ENOTCONN 未连接的套接字上的 send_file ,套接字上尚未完成与其同级的连接序列或者不再连接至其同级的 send_file
EWOULDBLOCK 套接字标记为非阻塞,并且请求的操作将阻塞。
ENOMEM 系统中没有可用内存来执行该操作。

PerformanceNote

通过利用网络缓冲区高速缓存, send_file 为文件传输提供了更高的性能和网络吞吐量。 对于大于 4K 个字节的文件,将对其进行重新命令。