MSG_OOB : 仅仅是通过tcp头的urgent 模式传送的,
且只会读取一个字节作为oob数据
例如:send(sockfd,\"1234\",strlen(\"1234\"),MSG_OOB);
只有最后一个字节:4 将被当作oob数据 ,其他数据\"123\"将被当作普通数据读取
需要注意:
此类数据通过信号 SIGURG 来通知 ,所以需要使用 signal / sigaction 来注册一个信号处理函数.
在signal 之前首先需要 fcntl(clientfd,F_SETOWN,getpid())
由于此信号是由套接字产生的, 而套接字的拥有者是操作系统 . 只有把套接字的拥有者设置为当前进程, SIGURG才会被
传递到此进程, 否则将接受不到SIGURG信号,只能接受普通数据.
MSG_PEEK : 偷窥一下缓冲区中有没有数据, recv(clientfd,buf,BUFSIZ,MSG_PEEK) ,并不会从缓冲区移除数据.
MSG_DONTWAIT : 不阻塞
oob_recv.c
#include \"util.h\"
#include <signal.h>
static void urg_handler(int sig);
int clientfd = 0;
int main(int argc, char ** argv)
{
int listenfd = socket(AF_INET, SOCK_STREAM,0);
struct sockaddr_in serv_addr,client_addr;
memset(&serv_addr,0,sizeof(serv_addr));
memset(&client_addr,0,sizeof(client_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = INADDR_ANY;
if(bind(listenfd,(SA*)&serv_addr,sizeof(serv_addr)) < 0){
perror(\"bind\");
return 0;
}
if(listen(listenfd,BACKLOG) < 0){
perror(\"listen\");
return 0;
}
socklen_t client_socklen =sizeof(client_addr);
clientfd = accept(listenfd,(SA*)&client_addr,&client_socklen);
//注意, 如果不设置套接字拥有者, 此进程将收不到SIGURG 信号.
fcntl(clientfd,F_SETOWN,getpid());
//注册信号函数
signal(SIGURG,urg_handler);
int n = 0;
char buf[BUFSIZ];
// while(1){
// printf(\"检查数据是否存在\\n\");
// n = recv(clientfd,buf,BUFSIZ,MSG_PEEK|MSG_DONTWAIT);
// printf(\"数据长度 : %d ,errno:%d\\n\", n,errno);
// if(n > 0){
// puts(\"有数据了\");
// break;
// }
//
// }
//接受普通数据.
while((n = recv(clientfd,buf,BUFSIZ,0)) != 0){
if( -1 == n){
perror(\"recv error\");
printf(\"error no : %d\\n\" ,errno);
continue;
}
buf[n] = 0;
printf(\"normal buf:%s\\n\",buf);
}
close(clientfd);
close(listenfd);
return 0;
}
static void urg_handler(int sig)
{
char buf[30];
//接受OOB数据, 只能接受最后一个字节, 其他字节作为普通数据接受
int n = recv(clientfd ,buf,30,MSG_OOB);
printf(\"oob len : %d\\n\" , n);
buf[n] = 0;
printf(\"oob data:%s\\n\" , buf);
}
oob_send.c
#include \"util.h\"
int main(int argc, char ** argv)
{
if ( argc != 3){
puts(\" ip port\");
return 0;
}
int sockfd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in sin;
memset(&sin,0,sizeof(sin));
sin.sin_port = htons(atoi(argv[2]));
sin.sin_addr.s_addr = inet_addr(argv[1]);
sin.sin_family = AF_INET;
connect(sockfd,(SA*)&sin,sizeof(sin));
char data[] = \"data1\" , data2[] = \"data2\";
char oob_data1[] = \"oobdata1\" , oob_data2[] = \"oob_data2\";
write(sockfd,data,strlen(data));
//发送oob数据 , 只有最后一个字节将被当作oob数据
send(sockfd,oob_data1,strlen(oob_data1),MSG_OOB);
write(sockfd,data2,strlen(data2));
//发送oob数据 , 只有最后一个字节将被当作oob数据
send(sockfd,oob_data2,strlen(oob_data2),MSG_OOB);
close(sockfd);
return 0;
}
结果:
normal buf:data1
oob len : 1
oob data:1
normal buf:oobdata
oob len : 1
oob data:2
normal buf:data2oob_data
继续阅读与本文标签相同的文章
-
Python快递鸟API接口对接(即时查询|物流跟踪|电子面单|单号识别)
2026-05-18栏目: 教程
-
免费物流快递单号查询API接口及使用教程
2026-05-18栏目: 教程
-
【译】Hadoop发生了什么?我们该如何做?
2026-05-18栏目: 教程
-
阿里云上云企业案例周刊·第2期
2026-05-18栏目: 教程
-
虚拟机模拟部署Extended Clusters(一)基础环境准备
2026-05-18栏目: 教程
