关于Winsock:Winsock编程注意事项:与协议无关的带外数据

流套接字抽象包括带外(OOB)数据的概念。 许多协议允许以某种方式将输入数据的部分标记为特殊,并且这些特殊数据块可以按正常顺序传递给用户。 示例包括X.25和其他OSI协议中的加急数据,以及BSD UNIX使用TCP中的紧急数据。 以下部分以与协议无关的方式描述OOB数据处理。 使用TCP紧急数据实现的OOB数据的讨论遵循与协议无关的解释。 在每次讨论中,recv的使用也意味着recvfrom,WSARecv和WSARecvFrom,对WSAAsyncSelect的引用也适用于WSAEventSelect。

 

协议独立的OOB数据

OOB数据是与每对连接的流套接字相关联的逻辑上独立的传输信道。可以独立于正常数据将OOB数据传递给用户。 抽象定义OOB数据工具必须一次支持至少一个OOB数据块的可靠传递。 该数据块可以包含至少一个字节的数据,并且至少一个OOB数据块可以在任何时间等待递送给用户。 对于支持带内信令的通信协议(例如TCP,其中紧急数据按正常数据顺序传送),系统通常从正常数据流中提取OOB数据并单独存储(留下间隙) 普通数据流)。 这允许用户在按顺序接收OOB数据和不按顺序接收OOB数据之间进行选择,而不必缓冲所有中间数据。 可以查看带外(OOB)数据。

用户可以使用带有SIOCATMARK IOCTL的ioctlsocket或WSAIoctl函数来确定是否有任何OOB数据正在等待读取。 对于正常数据流中OOB数据块的位置概念有意义的协议,例如TCP,Windows套接字服务提供者维护一个概念标记,指示正常数据流中OOB数据的最后一个字节的位置。 这对于支持SIOCATMARK的ioctlsocket或WSAIoctl函数的实现不是必需的。 是否需要存在或不存在OOB数据。

对于正常数据流中OOB数据块的位置概念有意义的协议,应用程序可以内联处理带外数据,作为普通数据流的一部分。 这是通过使用setsockopt函数设置套接字选项SO_OOBINLINE来实现的。 对于其中OOB数据块真正独立于普通数据流的其他协议,尝试设置SO_OOBINLINE会导致错误。 应用程序可以将ioctlsocket或WSAIoctl函数与SIOCATMARK IOCTL一起使用,以确定标记之前是否有任何未读的OOB数据。 例如,它可以使用此信息与其对等方重新同步,方法是确保在适当时丢弃数据流中标记之前的所有数据。

禁用SO_OOBINLINE(默认设置):

  • 如果应用程序使用WSAAsyncSelect注册通知,则Windows套接字会通知应用程序FD_OOB事件,其方式与使用FD_READ完全相同,以通知正常数据的存在。 也就是说,当OOB数据到达而没有先前排队的OOB数据时,FD_OOB被发布。 当使用MSG_OOB标志读取数据时也会发布FD_OOB,而某些OOB数据在读取操作返回后仍保持排队。 不会为OOB数据发布FD_READ消息。
  • 如果OOB数据在套接字上排队,则Windows套接字将从select中返回,并使用相应的exceptfds套接字集。
  • 应用程序可以使用MSG_OOB调用recv来随时读取紧急数据块。 OOB数据块跳转队列。
  • 应用程序可以在没有MSG_OOB的情况下调用recv来读取普通数据流。 OOB数据块不会出现在具有普通数据的数据流中。 如果在调用recv之后仍保留OOB数据,则Windows套接字在使用select时使用FD_OOB或exceptfds通知应用程序。
  • 对于OOB数据在普通数据流中具有位置的协议,单个recv操作不会跨越该位置。 一个recv返回标记之前的正常数据,并且需要第二个recv才能开始在标记之后读取数据。

启用SO_OOBINLINE后:

  • 不会为OOB数据发布FD_OOB消息。 出于select和WSAAsyncSelect函数的目的,OOB数据被视为正常,并通过在readfds中设置套接字或通过分别发送FD_READ消息来指示。
  • 应用程序无法调用recv,并将MSG_OOB标志设置为读取OOB数据块。 返回错误代码WSAEINVAL。
  • 应用程序可以在没有设置MSG_OOB标志的情况下调用recv。 任何OOB数据都在正常数据流中以正确的顺序传递。 OOB数据永远不会与普通数据混合。 必须有三个读取请求才能通过OOB数据。 第一个返回OOB数据块之前的正常数据,第二个返回OOB数据,第三个返回OOB数据之后的正常数据。 换句话说,保留了OOB数据块边界。

当SO_OOBINLINE关闭时,WSAAsyncSelect例程特别适合处理带外数据存在的通知。

 

TCP中的OOB数据

[!重要]
以下关于使用TCP紧急数据实现的带外数据(OOB)的讨论遵循伯克利软件分发中使用的模型。 用户和实施者应该意识到:

  • 目前,RFC 793存在两种相互矛盾的解释(其中引入了概念)。
  • Berkeley Software Distribution(BSD)中的OOB数据的实现不符合RFC 1122中指定的主机要求。

    具体地说,BSD中的TCP紧急指针指向紧急数据字节之后的字节,并且符合RFC的TCP紧急指针指向紧急数据字节。 因此,        如果应用程序将紧急数据从兼容BSD的实现发送到与RFC 1122兼容的实现,则接收器读取错误的紧急数据字节(它将位于数      据流中正确字节之后的字节读取为紧急数据) 字节)。

    为了最大限度地减少互操作性问题,建议应用程序编写者不要使用OOB数据,除非需要与现有服务进行互操作。 敦促                  Windows套接字供应商记录其产品实现的OOB语义(BSD或RFC 1122)。

具有URG(用于紧急)标志集的TCP段的到达指示TCP数据流内存在单字节的OOB数据。 OOB数据块大小为一个字节。 紧急指针是与TCP报头中的当前序列号的正偏移,其指示OOB数据块的位置(模糊地,如前所述)。 因此,它可能指向尚未收到的数据。

如果在包含紧急指针指向的字节的TCP段到达时禁用SO_OOBINLINE(默认值),则从数据流中删除OOB数据块(一个字节)并进行缓冲。 如果后续TCP段到达时设置了紧急标志(和一个新的紧急指针),则当前排队的OOB字节可能会丢失,因为它被新的OOB数据块替换(如Berkeley Software Distribution中所述)。 但是,它永远不会在数据流中被替换。

启用SO_OOBINLINE后,紧急数据将保留在数据流中。 因此,当新的TCP段到达包含紧急数据时,OOB数据块永远不会丢失。 现有的OOB数据标记将更新到新位置。

注意

设置SO_OOBINLINE套接字选项后,SIOCATMARK IOCTL始终返回TRUE,并将OOB数据作为普通数据返回给用户。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值