socket編程(3)廣播 多播
廣播
廣播是指在一個局域網中向所有的網上節點發送信息。這是UDP連接的一種
廣播有一個廣播組,即隻有一個廣播組內的節點才能收到發往這個廣播組的信息。什麼決定了一個廣播組呢,就是端口號,局域網內一個節點,如果設置了廣播屬性並監聽了端口號A後,那麼他就加入了A組廣播,這個局域網內所有發往廣播端口A的信息他都收的到。在廣播的實現中,如果一個節點想接受A組廣播信息,那麼就要先將他綁定給地址和端口A,然後設置這個socket的屬性為廣播屬性。如果一個節點不想接受廣播信息,而隻想發送廣播信息,那麼不用綁定端口,隻需要先為socket設置廣播屬性後,向廣播地址INADDR_BROADCAST的A端口發送udp信息即可。詳細的程序實現如下:
1.初始化
WSAStartup(MAKEWORD(2,2),&wsad);
2.創建一個UDP的socket
s=socket(AF_INET,SOCK_DGRAM,0);
3.如果這個socket希望收到信息,則需要綁定地址和這組廣播的端口號,如果隻是希望發送廣播信息,則不需要這步
SOCKADDR_IN udpAdress,sender;
int senferAddSize=sizeof(sender);
udpAdress.sin_family=AF_INET;
udpAdress.sin_port=htons(11114);
udpAdress.sin_addr.s_addr=inet_addr("10.11.131.32");
bind(s,(SOCKADDR*)&udpAdress,sizeof(udpAdress));
//這樣這個節點即可收到局域網內所有發往端口11114的廣播信息
4.設置socket的屬性為廣播
bool optval=true;
setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char*)&optval,sizeof(bool));
5.下麵就可以使用recvfrom或sendto來收發廣播信息了
這裏是接受,這是一個阻塞操作
ret=recvfrom(s,data,1000,0,(SOCKADDR*)&sender,&senferAddSize);
這裏是像該廣播組發送信息,注意發送的地址為廣播地址INADDR_BROADCAST,端口號為改組廣播的端口號11114
SOCKADDR_IN dstAdd;
dstAdd.sin_family=AF_INET;
dstAdd.sin_port=htons(11114);
dstAdd.sin_addr.s_addr=INADDR_BROADCAST;
sendto(s,data(),totalbyte,0,(SOCKADDR*)&dstAdd,sizeof(SOCKADDR));
多播
多播與廣播不同,多播是指一條信息向局域網內有限幾個節點傳遞,而廣播是不管某個節點是否在製定組內,都會向這個節點發送廣播信息,容易造成網絡負擔嚴重。
多播的實現是靠多播組,在局域網內,一個多播地址唯一的定義了一個多播組(端口號任意),可以使用的多播地址是有規定的,從224.0.0.0—239.255.255.255之間,但是其中的一些地址不能用,是用作特殊用途的:224.0.0.0 –224.0.0.2 224.0.1.1 224.0.0.9 224.0.1.24。一個節點如果想接受自某個多播組或向某個多播組發送信息,必須首先加入多播組,然後給予UDP發送。下麵是詳細的代碼實現。
1.初始化
WSAStartup(MAKEWORD(2,2),&wsad);
2.這裏傳建一個用於多播通信的socket,注意這個socket的參數為設置成多播
s=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF|WSA_FLAG_OVERLAPPED);
3.將socket綁定到一個本地地址、端口,和廣播不同,在多播中,無論是發送還是接收端都必須綁定一個本地地址,這個地址就是多播通信時處理信息的端口
udpAdress.sin_family=AF_INET;
udpAdress.sin_port=htons(22222);
udpAdress.sin_addr.s_addr=inet_addr("10.11.131.32");
bind(s,(SOCKADDR*)&udpAdress,sizeof(udpAdress));
4.定義多播組的地址
multiCastGroup.sin_family=AF_INET;
multiCastGroup.sin_port=htons(1111);此處端口任意,每個節點的可以設置成不同的
multiCastGroup.sin_addr.s_addr=inet_addr("224.0.0.3"); 此處需使用上麵規定地址段內的多播地址
5.加入這個多播組。注意這裏的函數返回了一個socket,這個socket不負責通信,隻是在脫離多播組時使用
SOCKET sockM=WSAJoinLeaf(s,(SOCKADDR*)&multiCastGroup,sizeof(multiCastGroup),NULL,NULL,NULL,NULL,JL_BOTH);
6.下麵使用recvfrom接受多播信息,或者使用sendto發送多播信息
ret=recvfrom(s,data,1000,0,(SOCKADDR*)&sender,&senferAddSize);
sendto(s,data(),totalbyte,0,(SOCKADDR*)&multiCastGroup,sizeof(multiCastGroup));
7.最後關閉清理
closesocket(sockM);
closesocket(s);
WSACleanup();
其他:
1)在多播組中,默認情況下一個發出多播信息的節點也會收到自己發送的信息,這稱為多播回環,可以關閉多播回環:
bool val=false;
setsocket(s,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)val,sizeof(val));
2)在多播時,通常要設置適當的TTL(TTL的值是多少,那麼多播信息就可以經過多少路由器,每經過一個路由器,TTl的值自動減1):
int val=3;
setsocket(s,IPPROTO_IP,IP_MULTICAST_TTL,(char*)val,sizeof(int));
最後更新:2017-04-02 06:51:36