MSG_OOB : 僅僅是經過tcp頭的urgent 模式傳送的,socket
且只會讀取一個字節做爲oob數據 例如:send(sockfd,"1234",strlen("1234"),MSG_OOB); 只有最後一個字節:4 將被看成oob數據 ,其餘數據"123"將被看成普通數據讀取
須要注意:tcp
此類數據經過信號 SIGURG 來通知 ,因此須要使用 signal / sigaction 來註冊一個信號處理函數.函數
在signal 以前首先須要 fcntl(clientfd,F_SETOWN,getpid()) 操作系統
因爲此信號是由套接字產生的, 而套接字的擁有者是操做系統 . 只有把套接字的擁有者設置爲當前進程, SIGURG纔會被code
傳遞到此進程, 不然將接受不到SIGURG信號,只能接受普通數據.orm
MSG_PEEK : 偷窺一下緩衝區中有沒有數據, recv(clientfd,buf,BUFSIZ,MSG_PEEK) ,並不會從緩衝區移除數據.進程
MSG_DONTWAIT : 不阻塞ip
oob_recv.cget
#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.cit
#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; }