请选择 进入手机版 | 继续访问电脑版

程序人生

 找回密码
 注册

QQ登录

只需一步,快速开始

程序人生 门户 程序员资讯 查看内容

TCP带外数据

2016-4-11 23:24| 发布者: sean| 查看: 583| 评论: 0

摘要: TCP/IP传输中有两类数据:普遍数据(带内数据)带外数据(Out Of Band, OOB)OOB就像古代行军打仗的侦查兵,不管前方多艰辛,它都要去报告紧急事情。OOB就是用于迅速通告对端本端所发生的重要事件,当然要比普遍数据 ...

TCP/IP传输中有两类数据:

  • 普遍数据(带内数据)
  • 带外数据(Out Of Band, OOB)

OOB就像古代行军打仗的侦查兵,不管前方多艰辛,它都要去报告紧急事情。OOB就是用于迅速通告对端本端所发生的重要事件,当然要比普遍数据权限高啊,它应该总是立即被发送。而不论发送缓冲区中是否有排队等待发送的普通数据(我有权插队,即可以映射到传输普通数据的连接中)或因流量控制而导致发送端的通告窗口大小为 0(即停止发送数据)

带外数据的传输可以:

  • (专车派送)使用一条独立的传输层连接
  • (有权插队)也可以映射到传输普通数据的连接中

但是UDP和TCP都没有真正实现带外数据,TCP是通过首部中的 紧急指针标志 和 紧急指针 两个字段,给应用程序提供了一种紧急方式。TCP 的紧急方式利用传输普通数据的连接来传输紧急数据。

注意:紧急数据并不是带外数据,它只是带外数据的一种体现

一. TCP 带外数据

通过:

  • TCP 发送带外数据
  • TCP 接收带外数据
  • 代码实例

进行学习

1. TCP 发送带外数据

假设一个进程已经往某个 TCP 连接的发送缓冲区中写入了 N 字节的普通数据,并等待其发送。如图1所示:

TCP带外数据

在数据被发送前,该进程又向这个连接写入了 3 字节的带外数据 “abc”。此时,待发送的 TCP 报文段的首部将被设置 URG 标志,并且紧急指针被设置为指向最后一个带外数据的下一字节(进一步减去当前 TCP 报文段的序号值得到其首部中的紧急偏移值)如下图所示:

TCP带外数据

如上图所见:发送端一次发送的多字节的带外数据中只有最后一字节被当作带外数据(字母c),而其他数据(字母a和b)被当成了普通数据。

注意:如果 TCP 模块以多个 TCP 报文段来发送如图 2 所示 TCP 发送缓冲区中的内容,则每个 TCP 报文段都将设置 URG 标志,并且它们的紧急指针指向同一个位置(数据流中带外数据的下一个位置),但只有一个 TCP 报文段真正携带带外数据。

2.TCP 接收带外数据

TCP 接收端只有在接收到紧急指针标志时才检查紧急指针,然后根据紧急指针所指的位置确定带外数据的位置,并将它读入一个特殊的缓存中。这个缓存只有1字节,称为带外缓存。如果上层应用程序没有及时将带外数据从带外缓存中读出,则后续的带外数据(如果有的话)将覆盖它。

前面讨论的带外数据的接收过程是 TCP 模块接收带外数据的默认方式。如果我们给 TCP 连接设置了SO_OOBINLINE 选项,则带外数据将和普通数据一样被 TCP 模块存放在 TCP 接收缓冲区中。此时应用程序需要像读取普通数据一样来读取带外数据。这种情况下,使用紧急指针来区分普通数据和带外数据,紧急指针可以用来指出带外数据的位置, socket 编程接口也提供了系统调用来识别带外数据。

3.TCP处理带外数据实例

用于TCP流数据读写的系统调用中:

#include 
#include 
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t send(int sockfd, const void *buf, size_t len, int flags); 

其中buflen参数分别指定读或写缓冲区的位置和大小,flags参数通常设置为0,但flags参数为数据收发提供了额外的控制,如下:

TCP带外数据

那么接下来通过MSG_OOB选项给应用程序提供了发送和接收带外数据的方法

示例代码在OOBTest

通过tcpdump工具和服务器程序的输出:

got 5 bytes of normal data'123ab'
got 1 bytes of oob data'c'
got 3 bytes of normal data'123' 

由此可见,客户端发送给服务器的3字节的带外数据“abc”中,仅有最后一个字符“c”被服务器当成真正的带外数据接收。并且,服务器对正常数据的接收将被带外数据截断,即前一部分正常数据“123ab”和后续的正常数据“123”是不能被一个recv调用全部读出的。

tcpdump的输出内容如下:

IP 192.168.1.108.60460>192.168.1.109.54321:
Flags[P.U],seq 4:7,ack 1,win 92,urg 3,
options[nop,nop,TS val 102794322 ecr 154703423],
length 3 

这里我们第一次看到tcpdump输出标志U,这表示该TCP报文段的头部被设置了紧急标志。“urg 3”是紧急偏移值,它指出带外数据在字节流中的位置的下一字节位置是7(3+4,其中4是该TCP报文段的序号值相对初始序号值的偏移)。因此,带外数据是字节流中的第6字节,即字符“c”。

二.带外标记

这个标记就是用于内核检查TCP紧急标识,然后通知应用程序来处理。

内核通知应用程序带外数据到达有两种常见的方式:

  • I/O 复用产生的异常事件
  • SIGURG 信号

但是,即使应用程序得到了有带外数据需要接收的通知,还需要知道带外数据在数据流中的具体位置,才能准确接收带外数据,通过sockatmark

#include
int sockatmark(int sockfd);

sockatmark判断sockfd是否处于带外标记,即下一个被读取到的数据是否是带外数据。如果是,sockatmark返回1,此时我们就可以利用带MSG_OOB标志的recv调用来接收带外数据。如果不是,则sockatmark返回0。

/* 检测套接字接收缓冲区是否处于带外标记 */  
   if(sockatmark(connfd))  
       printf("at OOB mark\n");  
   /* 读取数据,并显示这些数据 */  
       if ( (n = read(connfd, buff, sizeof(buff)-1)) == 0) {  
           printf("received EOF\n");  
           exit(0);  
       }  
       buff[n] = 0;    /* null terminate */  
       printf("read %d bytes: %s\n", n, buff); 

鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论

热门文章
微软醒悟,推出新一代跨平台开发利器Apache Cordowa
微软醒悟,推出新一代跨平台开发利器Apache
Apache Cordowa是个什么东西呢?Apache Cordowa其实就是一套API,它可以让程序开发者使
VS开发IOS,Android应用,移动开发者的春天来了
VS开发IOS,Android应用,移动开发者的春天
有时候为了开发IOS,Android应用,我们不得不去学习java,object-c等编程语言,而对于.
.net程序员的福音:.NET Native预览版 C#可编译为本地机器码
.net程序员的福音:.NET Native预览版 C#可
微软在 MSDN 博客上宣布了.NET Native 的开发者预览版。.NET Native 可以将 C# 代码编
如何使用VS2012 的Schema比对功能
如何使用VS2012 的Schema比对功能
首先需要一个现成的数据库才能完成Schema的比对,您可以下载微软的实例数据库ContosoB
微软的粉丝们,永远不要停止学习的脚步,2014要学习M#了
微软的粉丝们,永远不要停止学习的脚步,20
先来说下M#,M#也被称为M Sharp,用于开发Midori的语言,也随着操作系统一同构建出来。这

关于程序人生网|小黑屋|手机版|Archiver|

程序人生 | QQ

粤公网安备 44040202000007号

( 粤ICP备13038131号-1 )

返回顶部