当从socket读取数据时,通常会用到read/write系列函数。由于读写函数都是配对的,这里以read系列为例,通过man手册可以看到:
ssize_t read(int fd, void *buf, size_t count);
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
这些函数最主要的区别,一方面是可以通过提供了Flag参数来设置特性;另一方面是支持更高效的“离散读或聚集写”(scatter input or gather output)结构操作buffer。本期讲解的就是Flag参数中的MSG_OOB。
实际上大多数应用可能不会使用到函数中提供的flag参数,这里介绍MSG_OOB,在telnet、ftp应用中有使用到。
MSG_OOB是用来设置接受“带外数据”(out-of-band data),用于告知应用层处理较为紧急的数据。这个特性的底层逻辑是由于TCP的协议头中的FLAG有URG标志;再配合紧急指针标记紧急的数据是什么,紧急数据限制为1个字节。如果忘记了TCP的协议头,可以回顾下:
TCP协议头
默认情况下,带外数据是存放在专门的⼀个字节的带外数据缓冲区中的。⼀个tcp连接只有⼀个带外数据,第⼆个到来的带外数据会覆盖第⼀个到来的带外数据。在获取带外数据的时候,一般按如下的编程逻辑:
1、通过信号处理SIGURG,过程⾸先设置⽂件描述字的进程属主:
fcntl(sockfd, F_SETOWN,getpid())
2、然后注册SIGURG信号处理句柄并且在句柄⾥⾯读取带外数据
这里以一个服务器/客户端的例子来测试下,server端的代码如下:
server端
客户端的代码:
client端
输出如下:
输出
通过抓包分析我们可以看到,server端按照client中的代码先收到普通数据,然后收到带有URG标志的数据;收到带有URG标志的包触发了server端的OOB函数。
留言与评论(共有 0 条评论) “” |