OOB (2)

来源:互联网 发布:做衣服的软件 编辑:程序博客网 时间:2024/06/01 08:45

Out Of Band (OOB) 带外数据

有个不错的英文站介绍了这个OOB,http://alas.matf.bg.ac.rs/manuals/lspe/snode=125.html 

 

带外数据,也叫紧急数据,跟普通数据没有太大区别,就是在接收时,会单独存放在一个独立缓冲中;读取时可以先被读取到(读取方式与普通数据稍有差别)。每次紧急数据只能发送一个字符。

 

tcpdump抓包得到信息如下

        0x0040:  c605 6e6f 726d 616c 2064 6174 610a       ..normal.data.

15:57:20.602500 IP localhost.localdomain.46968 > localhost.localdomain.11827: P 25:64(39) ack 1 win 257 urg 39 <nop,nop,timestamp 4176659973 4176659973>

        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.

        0x0010:  005b a39d 4000 4006 98fd 7f00 0001 7f00  .[..@.@.........

        0x0020:  0001 b778 2e33 a1d3 65b5 a141 8756 8038  ...x.3..e..A.V.8

        0x0030:  0101 fe4f 0027 0101 080a f8f2 c605 f8f2  ...O.'..........

        0x0040:  c605 6e6f 726d 616c 2064 6174 610a 6e6f  ..normal.data.no

        0x0050:  726d 616c 2064 6174 610a 6e6f 726d 616c  rmal.data.normal

        0x0060:  2064 6174 610a 6162 63                   .data.abc

38表示含有紧急数据,33表示紧急数据在数据段的偏移,数据段开始在n的位置,便宜0x33(51)正好是c的位置。

 

示例代码如下:

[root@M6 oob]# cat sv.c

#include <sys/types.h>

#include <errno.h>

#include <sys/socket.h>

#include <stdio.h>

#include <netinet/in.h>

#include <netinet/ip.h>

#include <unistd.h>

 

int main()

{

        int fd = socket(PF_INET, SOCK_STREAM, 0);

        if(fd < 0)

                perror("socket fail\n");

 

        struct sockaddr_in addr;

        memset(&addr, 0, sizeof(struct sockaddr_in));

        addr.sin_family = AF_INET;

        addr.sin_port = htons(11827);

        addr.sin_addr.s_addr = inet_addr("127.0.0.1");

 

        if(bind(fd, &addr, sizeof(struct sockaddr_in)) < 0)

                perror("bind fail\n");

        if(listen(fd, 3) < 0)

                perror("listen fail\n");

 

        char buf[1024];

        int cl_fd = 0;

        int read_cnt = 0;

        while(1)

        {

                cl_fd = 0;

                if((cl_fd = accept(fd, NULL, NULL)) < 0)

                {

                        perror("accept fail\n");

                        break;

                }

                sleep(5);

                while(1)

                {

                        while(1)

                        {

                                if((read_cnt = recv(cl_fd, buf, 9, MSG_DONTWAIT|MSG_OOB)) >= 0)

                                {

                                        buf[read_cnt] = 0;

                                        printf("MSG_OOB:%s=\n", buf);

                                        continue;

                                }

                                else

                                        break;

                        }

 

                        if((read_cnt = recv(cl_fd, buf, 1024, MSG_WAITALL)) < 0)

                        {

                                perror("recv normal data fail\n");

                                break;

                        }

                        else if(read_cnt == 0)

                        {

                                close(cl_fd);

                                printf("%s", "client exit\n");

                                break;

                        }

                        buf[read_cnt] = 0;

                        printf("MSG:%s=\n", buf);

                }

        }

        printf("%S", "done for all\n");

        return 0;

}

[root@M6 oob]# cat cl.c

#include <sys/types.h>

#include <sys/socket.h>

#include <stdio.h>

#include <netinet/in.h>

#include <netinet/ip.h>

 

int main()

{

        int fd = socket(PF_INET, SOCK_STREAM, 0);

        if(fd < 0)

                perror("socket fail\n");

 

        struct sockaddr_in addr;

        memset(&addr, 0, sizeof(struct sockaddr_in));

        addr.sin_family = AF_INET;

        addr.sin_port = htons(11827);

        addr.sin_addr.s_addr = inet_addr("127.0.0.1");

        if(connect(fd, &addr, sizeof(struct sockaddr_in)) < 0)

                perror("connect fail\n");

 

        int i = 0;

        while(1)

        {

                if(i == 5)

                        if(send(fd, "abc", 3, MSG_OOB) != 3)

                                perror("send oob fail\n");

                if(send(fd, "normal data\n", strlen("normal data\n"), 0) < 0)

                        perror("send normal data fail\n");

                i++;

                if(i == 10)

                        break;

        }

        close(fd);

        printf("%s","data send ok\n");

        return 0;

}

 

 

 

[root@M6 oob]# ./sv 

MSG_OOB:c=

MSG:normal data

normal data

normal data

normal data

normal data

ab=

MSG:normal data

normal data

normal data

normal data

normal data

=

client exit

 

其中的sleep正好可以让sv休一会,保证数据都已经到位,在sleep之后,通过MSG_DONTWAIT|MSG_OOB读取紧急数据,这时候就有了。

如果把sleep去掉,得到的数据就是这样的了:

[root@M6 oob]# ./sv 

MSG:normal data

normal data

normal data

normal data

normal data

ab=

MSG_OOB:c=

MSG:normal data

normal data

normal data

normal data

normal data

=

client exit

原因是,没有sleep,sv不会停下,read会接收所有数据,tcpdump抓包得到

        0x0040:  a0d6                                     ..

18:08:15.427368 IP localhost.localdomain.53051 > localhost.localdomain.11827: P 61:64(3) ack 1 win 257 urg 3 <nop,nop,timestamp 4184514774 4184514774>

        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.

        0x0010:  0037 6c9a 4000 4006 d024 7f00 0001 7f00  .7l.@.@..$......

        0x0020:  0001 cf3b 2e33 8fad cc82 8fd7 0196 8038  ...;.3.........8

        0x0030:  0101 fe2b 0003 0101 080a f96a a0d6 f96a  ...+.......j...j

        0x0040:  a0d6 6162 63                             ..abc

说明过来时,只有ab与c一起被发送过来,而这时,sv卡在普通的recv中,所以先是ab被打印出来,当下次循环中,读取紧急数据时,c才被读取出来了。