1. 带外数据的发送。
函数: send(fd, 'a', 1, MSG_OOB);
tcp内核: 不管什么情况(忽略掉nagle算法和窗口大小等因素),立刻发送一个urg包给对端,告诉对方我要发送OOB了和这个内容的位置。需要注意的是,实际的‘a'内容也是通过正常的发送缓冲区发送出去的。当发送区满的时候或是通告的窗口为0,紧急数据本身实际上也阻塞了,不管怎样至少一个urg通知包是发给对方了。但是此时接收端试图读取该紧急数据时,就会返回一个EWOULDBLOCK错误
2. 带外数据的接收。
默认情况下,带外数据是存放在专门的一个字节的带外数据缓冲区中的。一个tcp连接只有一个带外数据,第二个到来的带外数据会覆盖第一个到来的带外数据(如果程序没有处理第一个到来的带外数据的话)
函数: a. 通过信号处理SIGURG,过程首先设置文件描述字的进程属主,fcntl(sockfd, F_SETOWN, getpid());然后注册SIGURG信号处理句柄并且在句柄里面读取带外数据
b. select 的异常条件。当带外数据到达时,sockfd会产生异常。但是需要注意的情况是,sockfd上的异常不会自动清除。当读取过带外数据之后,应该先将sockfd从异常fd_set中移除(否则将会进入死循环,一直检测到异常,然后读取带外数据,但是带外数据已经在第一次时就被读取了,于是就会返回EINVAL的错误),然后等待读取一部分正常数据之后,再设置sockfd到异常fd_set
c. 通过设置SO_OOBINLINE 和 sockatmark()函数。首先设置SO_OOBINLINE在普通接收缓冲区中接收带外数据。然后程序读取该缓冲区时结合seockatmark 检测是否当前位置属于带外数据区。注意,假设这样的而一个缓冲区内容123456x789.其中x为带外数据。read时内核会将123456 和 x789中间做标记。程序读取到x时会自动停住。然后下次继续读取剩下的(这是通过sockatmark就会发现处于带外数据区,此时如果read(sockfd, buf, 1)的话buf里面就时带外数据了(x).个人觉得这个方法比较耗费资源的
阅读(1379) | 评论(0) | 转发(0) |