transmitFile 函数 (mswsock.h)
TransmitFile 函数通过连接的套接字句柄传输文件数据。 此函数使用操作系统的缓存管理器检索文件数据,并通过套接字提供高性能的文件数据传输。
语法
BOOL TransmitFile(
SOCKET hSocket,
HANDLE hFile,
DWORD nNumberOfBytesToWrite,
DWORD nNumberOfBytesPerSend,
LPOVERLAPPED lpOverlapped,
LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
DWORD dwReserved
);
参数
hSocket
已连接套接字的句柄。 TransmitFile 函数将通过此套接字传输文件数据。 由 hSocket 参数指定的套接字必须是SOCK_STREAM、SOCK_SEQPACKET 或 SOCK_RDM 类型的面向连接的套接字。
hFile
TransmitFile 函数传输的打开文件的句柄。 由于操作系统按顺序读取文件数据,因此可以通过使用 FILE_FLAG_SEQUENTIAL_SCAN 打开句柄来提高缓存性能。
hFile 参数是可选的。 如果 hFile 参数为 NULL,则仅传输标头和/或结尾缓冲区中的数据。 任何其他操作(如套接字断开连接或重用)均按 dwFlags 参数指定执行。
nNumberOfBytesToWrite
文件中要传输的字节数。 当 TransmitFile 函数发送指定数量的字节或发生错误时(以先发生者为准)时完成。
将此参数设置为零以传输整个文件。
nNumberOfBytesPerSend
每个发送操作中发送的每个数据块的大小(以字节为单位)。 此参数由 Windows 的套接字层用于确定发送操作的块大小。 若要选择默认发送大小,请将此参数设置为零。
nNumberOfBytesPerSend 参数适用于对单个发送请求的大小有限制的协议。
lpOverlapped
指向 OVERLAPPED 结构的指针。 如果套接字句柄已以重叠方式打开,请指定此参数以实现重叠 (异步) I/O 操作。 默认情况下,套接字句柄以重叠方式打开。
可以通过设置 OVERLAPPED 结构的 Offset 和 OffsetHigh 成员,使用 lpOverlapped 参数在文件中指定开始文件数据传输的 64 位偏移量。 如果 lpOverlapped 是 NULL 指针,则数据传输始终从文件中的当前字节偏移量开始。
当 lpOverlapped 不为 NULL 时,重叠的 I/O 可能不会在 TransmitFile 返回之前完成。 在这种情况下,TransmitFile 函数返回 FALSE,WSAGetLastError 返回ERROR_IO_PENDING或WSA_IO_PENDING。 这使调用方能够在文件传输操作完成时继续处理。 完成数据传输请求后,Windows 会将由 OVERLAPPED 结构的 hEvent 成员指定的事件或 hSocket 指定的套接字设置为信号状态。
lpTransmitBuffers
指向 TRANSMIT_FILE_BUFFERS 数据结构的指针,该结构包含指向在发送文件数据之前和之后要发送的数据的指针。 如果只想传输文件数据,则应将此参数设置为 NULL 指针。
dwReserved
一组标志,用于修改 TransmitFile 函数调用的行为。 dwFlags 参数可以包含 Mswsock.h 头文件中定义的以下选项的组合:
标志 | 含义 |
---|---|
|
所有要传输的数据文件完成排队后,启动传输层断开连接。 |
|
准备要重复使用的套接字句柄。 仅当同时指定 TF_DISCONNECT 时,此标志才有效。
当 TransmitFile 请求完成时,套接字句柄可以传递给先前用于建立连接的函数调用,例如 AcceptEx 或 ConnectEx。 这种重用是相互排斥的:例如,如果已为套接字调用 AcceptEx 函数,则仅允许对 AcceptEx 函数的后续调用重复使用,不允许对 ConnectEx 的后续调用重复使用。 注意 套接字级别文件传输受基础传输行为的约束。 例如,TCP 套接字可能受 TCP TIME_WAIT状态的约束,从而导致 TransmitFile 调用延迟。
|
|
指示 Windows 套接字服务提供程序使用系统的默认线程来处理较长的 TransmitFile 请求。 可以使用以下注册表参数作为 REG_DWORD调整系统默认线程: \ HKEY_LOCAL_MACHINECurrentControlSet\服务\渔农 处\参数\TransmitWorker |
|
指示 Windows 套接字服务提供程序使用系统线程来处理较长 的 TransmitFile 请求。 |
|
指示驱动程序使用内核异步过程调用 (APC) 而不是工作线程来处理较长 的 TransmitFile 请求。 Long TransmitFile 请求定义为需要从文件或缓存读取多个单个请求;因此,请求取决于文件的大小和发送数据包的指定长度。
使用TF_USE_KERNEL_APC可以提供显著的性能优势。 但是, (虽然不太可能) ,但启动上下文 TransmitFile 的线程正用于繁重的计算;这种情况可能会阻止 APC 启动。 请注意,Winsock 内核模式驱动程序使用正常的内核 APC,只要线程处于等待状态就会启动,这与用户模式 APC 不同,只要线程处于在用户模式中启动的可警报等待状态,就会启动) 。 |
|
立即完成 TransmitFile 请求,而不会挂起。 如果指定了此标志并且 TransmitFile 成功,则表示数据已被系统接受,但不一定被远程端确认。 不要将此设置与 TF_DISCONNECT 和 TF_REUSE_SOCKET 标志一起使用。
注意 如果正在发送的文件不在文件系统缓存中,则请求会提交。
|
返回值
如果 TransmitFile 函数成功,则返回值为 TRUE。 否则,返回值为 FALSE。 若要获取扩展错误信息,请调用 WSAGetLastError。 WSA_IO_PENDING或ERROR_IO_PENDING错误代码指示重叠操作已成功启动,稍后将指示完成。 任何其他错误代码都指示重叠的操作未成功启动,并且不会发生完成指示。 在这种情况下,应用程序应处理ERROR_IO_PENDING或WSA_IO_PENDING。
返回代码 | 说明 |
---|---|
您的主机中的软件中止了已建立的连接。 如果虚拟线路因超时或其他故障而终止,则返回此错误。 | |
远程主机强行关闭现有连接。 当远程端重置虚拟线路时,会为流套接字返回此错误。 因为套接字不可再用,应用程序应关闭套接字。 | |
系统尝试在调用中使用指针参数时检测到指针地址无效。 如果 lpTransmitBuffers 或 lpOverlapped 参数未完全包含在用户地址空间的有效部分中,则返回此错误。 | |
提供的参数无效。 如果 hSocket 参数指定 类型为 SOCK_DGRAM 或 SOCK_RAW 的套接字,则返回此错误。 如果 dwFlags 参数设置了 TF_REUSE_SOCKET 标志,但未设置 TF_DISCONNECT 标志,则返回此错误。 如果 lpOverlapped 指向的 OVERLAPPED 结构中指定的偏移量不在文件中,也会返回此错误。 如果将 nNumberOfBytesToWrite 参数设置为大于 2,147,483,646 的值(32 位整数减 1 的最大值),则也会返回此错误。 | |
套接字操作遇到死网。如果网络子系统发生故障,则返回此错误。 | |
由于操作执行过程中持续的活动检测到故障,连接损坏。 | |
无法执行某个套接字操作,因为系统缺少足够的缓冲空间或队列已满。 如果 Windows 套接字提供程序报告缓冲区死锁,也会返回此错误。 | |
由于套接字未连接,因此不允许发送或接收数据的请求。 | |
某个操作尝试对非套接字执行操作。 如果 hSocket 参数不是套接字,则返回此错误。 | |
因为该方向的套接字在上一关闭调用中已关闭,发送或接收数据的请求被禁止。 如果已关闭套接字以发送,则返回此错误。 在套接字上调用关闭函数并将 how 参数设置为 SD_SEND 或 SD_BOTH 后,无法在套接字上调用 TransmitFile。 | |
应用程序未调用 WSAStartup 函数,或者 WSAStartup 失败。 在使用 TransmitFile 函数之前,必须成功调用 WSAStartup。 | |
重叠的 I/O 操作正在进行中。 如果成功启动重叠的 I/O 操作并指示稍后将指示完成,则返回此值。 | |
由于发生线程退出或应用程序请求,I/O 操作已中止。 如果由于套接字关闭、 WSAIoctl 中的“SIO_FLUSH”命令的执行或启动重叠请求的线程在操作完成之前退出而取消了重叠操作,则返回此错误。
注意 当给定线程退出时,将取消由给定线程启动的所有 I/O。 对于重叠套接字,如果在异步操作完成之前关闭线程,挂起的异步操作可能会失败。 有关详细信息,请参阅 ExitThread。
|
注解
TransmitFile 函数使用操作系统的缓存管理器来检索文件数据,并通过套接字提供高性能的文件数据传输。
TransmitFile 函数仅支持 SOCK_STREAM、SOCK_SEQPACKET 和 SOCK_RDM 类型的面向连接的套接字。 不支持 SOCK_DGRAM 和 SOCK_RAW 类型的套接字。 TransmitPackets 函数可与 SOCK_DGRAM 类型的套接字一起使用。
使用对 TransmitFile 函数的单个调用可以传输的最大字节数为 2,147,483,646,即 32 位整数减 1 的最大值。 在单个调用中发送的最大字节数包括 lpTransmitBuffers 参数指向的文件数据之前或之后发送的任何数据,以及 nNumberOfBytesToWrite 参数中指定的值,用于发送的文件数据长度。 如果应用程序需要传输大于 2,147,483,646 字节的文件,则可以使用对 TransmitFile 函数的多次调用,每次调用传输不超过 2,147,483,646 个字节。 对于大于 2,147,483,646 字节的文件,将 nNumberOfBytesToWrite 参数设置为零也将失败,因为在这种情况下 ,TransmitFile 函数将使用文件大小作为要传输的字节数的值。
工作站和客户端版本的 Windows 通过将系统上允许的并发 TransmitFile 操作数限制为最多两个来优化 TransmitFile 函数,以最大程度地减少内存和资源利用率。 在 Windows Vista、Windows XP、Windows 2000 Professional 和 Windows NT Workstation 3.51 及更高版本上,仅同时处理两个未完成的 TransmitFile 请求;第三个请求将等到前面的请求之一完成。
服务器版本的 Windows 优化 了 TransmitFile 函数,实现高性能。 在服务器版本上,对系统上允许的并发 TransmitFile 操作数没有默认限制。 在 Windows 的服务器版本上使用 TransmitFile 时,预期性能会更好。 在 Windows 的服务器版本中,可以通过创建注册表项并为以下REG_DWORD设置值,对并发传输文件操作的最大数量设置限制:
\ HKEY_LOCAL_MACHINECurrentControlSet\服务\渔农 处\参数\MaxActiveTransmitFileCount
如果使用 TCP 套接字 (协议IPPROTO_TCP) 同时指定了 TF_DISCONNECT 和 TF_REUSE_SOCKET 标志来调用 TransmitFile 函数,则在满足以下两个条件之前,调用不会完成。
- 已读取远程端发送的所有挂起接收数据, (在 TCP 套接字上从远程端接收 FIN) 之前接收。
- 远程端已关闭连接, (完成正常 TCP 连接关闭) 。
如果在 lpOverlapped 参数设置为 NULL 的情况下调用 TransmitFile 函数,则操作将作为同步 I/O 执行。 在发送文件之前,函数不会完成。
Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。
Windows 8.1和Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。
QoS 说明
TransmitFile 函数允许设置两个标志,TF_DISCONNECT或TF_REUSE_SOCKET,这些标志在传输文件后将套接字返回到“断开连接、可重用”状态。 不应在请求服务质量的套接字上使用这些标志,因为服务提供商可能会在文件传输完成之前立即删除与套接字关联的任何服务质量。 启用 QoS 的套接字的最佳方法是在文件传输完成后调用 closesocket 函数,而不是依赖于这些标志。要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows 8.1,Windows Vista [桌面应用 |UWP 应用] |
最低受支持的服务器 | Windows Server 2003 [桌面应用 | UWP 应用] |
目标平台 | Windows |
标头 | mswsock.h (包括 Mswsock.h) |
Library | Mswsock.lib |
DLL | Mswsock.dll |