日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络编程——进阶篇

發(fā)布時間:2023/12/31 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络编程——进阶篇 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
網(wǎng)絡(luò)超時 :網(wǎng)絡(luò)通信中,好多超時會使進(jìn)程阻塞,這里共有三種處理方法
方法一:設(shè)置sock的超時屬性SO_RCVTIMEO
參考代碼:struct timeval tv;
tv.tv_sec=5
tv.tv_usec=0?
setsockopt(fd,SOL_SOCKET,SO_RECVTIMEO,&tv,sizeof(tv))//設(shè)置5s后超時
recv/recvfrom //5s后若還在阻塞,則返回,同時置errno=11
方法二:并發(fā)IO的select,設(shè)置超時屬性
參考代碼:struct timeval tv;
fd_set rdfs;
tv.tv_sec=5
tv.tv_usec=0
FD_ZERO(&rdfs);
FD_SET(sockfd,&rdfs);
if(select(sockfd+1,&rdfs,NULL,NULL,&tv)>0)
{recv/recvfrom}
方法三、SIGALRM信號捕捉(最常用)
在讀操作前(可能阻塞),啟動定時器,過一定的時刻發(fā)送SIGALRM信號,設(shè)置信號屬性,信號函數(shù)處理完后,從阻塞的下一句開始執(zhí)行
信號處理函數(shù):void handler(int signo){return }
設(shè)置信號屬性:struct sigaction act //定義sigaction 結(jié)構(gòu)體變量,臨時保存信號屬性
signaction(SIGALRM,NULL,&act)//讀取當(dāng)前屬性到act中
act.sa_handler=handler;
act.sa_flags &=~SA_RESTART;//清零,設(shè)置信號函數(shù)執(zhí)行完后,從系統(tǒng)調(diào)用(讀時阻塞)的下一句開始執(zhí)行
sigaction(SIGALRM,&act,NULL);
使用:alarm(5)
if(recv()<0)如果在這里阻塞5s,則系統(tǒng)發(fā)出SIGALRM,默認(rèn)殺死進(jìn)程,經(jīng)過設(shè)置后,可以從這條語句的后面開始執(zhí)行
思考:其實信號默認(rèn)的SA_RESTART為0,即信號處理函數(shù)執(zhí)行完后,就從下一個語句開始執(zhí)行,當(dāng)然,前提是信號沒有殺死進(jìn)程,所以,是不是可以用 signal(SIGALRM,hander)來代替?
答案:不可以,signal會修該SA_RESTART,所以,執(zhí)行完后,會繼續(xù)返回到阻塞的地方執(zhí)行

廣播 :可以向局域網(wǎng)中所有的主機(jī)發(fā)送消息(根據(jù)ip和port),數(shù)據(jù)報的特點就是以太網(wǎng)頭的目標(biāo)MAC為FFFFFFF。
發(fā)送端:建立socket,通過setsockopt設(shè)置為可以發(fā)廣播,設(shè)定sockaddr,然后就sendto發(fā)送
接收端:建立socket,綁定ip(發(fā)送端可以不用綁定ip,但是接收端需要知道自己所綁定的ip后才能接收)
若綁定的是自己主機(jī)的ip,則只能接收單播,綁定為廣播ip,則只可以接收廣播,綁定0,單播組播廣播都可以接收



組播 :向特定的組發(fā)消息,它的數(shù)據(jù)幀以太頭的目標(biāo)MAC格式:10:00:5e:*:*:*,后面三字節(jié)是組播地址的后幾位有關(guān)。
發(fā)送端:建立socket,指定組播地址,向組播發(fā)送消息。(socket默認(rèn)是可以發(fā)送組播消息的)
接收端:建立socket,綁定ip(ip選擇和上述一樣),允許數(shù)據(jù)鏈路層接收組播消息,接收消息。
允許鏈路層接收組播消息是難點:默認(rèn)的以太網(wǎng)卡只能接收兩種類型的目標(biāo)MAC地址:自身MAC(單播),FFFFFF(組播)。
而組播數(shù)據(jù)幀目標(biāo)MAC的地址為:10:00:5e:*:*:*,可以通過setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mrep,sizeof(mrep))里的mrep來指定以太網(wǎng)卡可以接收的組播。



問題:組播接受程序可以接受廣播包嗎?那反過來呢?(老師說,組播接受程序可以接收廣播包,不甚理解,甚至覺得老師說錯了)
(后來發(fā)現(xiàn)是我錯了!在教室坐的久了腦袋秀逗了。在吃飯的路上才恍然大悟)
原因:鏈路層可以接收并向上傳遞兩個類型的數(shù)據(jù)幀:目標(biāo)MAC是自身(單播)、FFFFFF(廣播)。其余的數(shù)據(jù)幀雖然接收,但是在鏈路層比較后都已經(jīng)丟棄。
在組播中,接收程序需要設(shè)定鏈路層網(wǎng)卡可以處理組播的數(shù)據(jù)幀。所以他不僅能接收廣播,還能接收組播(就是因為它比廣播多設(shè)定了接收端MAC)。

在執(zhí)行過程中,組播的接收程序不能再綁定組播地址,而是0.

實例:

接收端:組播接收端

#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #include<string.h> #include<stdlib.h> #include<sys/select.h> #define N 64int main(int argc,char *argv[]) {int fd;struct sockaddr_in recad,peerad;char buf[N]={};int len;len=sizeof(peerad);memset(&recad,0,sizeof(recad));memset(&peerad,0,sizeof(peerad));recad.sin_family=PF_INET;recad.sin_port=htons(atoi(argv[2]));recad.sin_addr.s_addr=inet_addr(argv[1]);if((fd=socket(PF_INET,SOCK_DGRAM,0))<0){perror("socket");exit(-1);}if((bind(fd,(struct sockaddr*)&recad,sizeof(recad)))<0){printf("bind");exit(-1);}struct ip_mreq mreq;memset(&mreq,0,sizeof(mreq));mreq.imr_multiaddr.s_addr=inet_addr("224.10.10.1");mreq.imr_interface.s_addr=htons(INADDR_ANY);if(setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq))<0){perror("setsockopt");exit(-1);}while(1){memset(buf,0,N);recvfrom(fd,buf,N,0,(struct sockaddr*)&peerad,&len);printf("[%s %d] %s\n",inet_ntoa(peerad.sin_addr),ntohs(peerad.sin_port),buf);}}
發(fā)送端:廣播的發(fā)送端

#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #include<string.h> #include<stdlib.h> #include<sys/select.h> #define N 64int main(int argc,char *argv[]) {int fd;struct sockaddr_in broad;char buf[N]={"hello everyone!"};int val=1;int len;len=sizeof(val);memset(&broad,0,sizeof(broad));broad.sin_family=PF_INET;broad.sin_port=htons(atoi(argv[2]));broad.sin_addr.s_addr=inet_addr(argv[1]);if((fd=socket(PF_INET,SOCK_DGRAM,0))<0){perror("socket");exit(-1);}if(setsockopt(fd,SOL_SOCKET,SO_BROADCAST,&val,len)<0){printf("getsockopt");exit(-1);}while(1){sendto(fd,buf,N,0,(struct sockaddr*)&broad,sizeof(broad));sleep(1);}}
發(fā)送端:編譯:gcc -o sender sender.c

./send 192.168.1.255 8888

接收端:編譯:gcc -o recever recever.c

./recever 0 8888

接收端執(zhí)行時ip一定為0,這樣,雖然他是一個組播接收程序,但是還可以接收廣播。

總結(jié)

以上是生活随笔為你收集整理的网络编程——进阶篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。