說明:本文僅針對ipv4區域網發現技術有很多,常用組播(或稱為多播):一台裝置傳送組播包,其他裝置加入組播組,接收到組播包時即可知曉傳送端ip,接收端回應約定資料即可讓傳送端也得知這些接收端的ip。
ipv4的d類位址(224.0.0.0至239.255.255.255)是ipv4多播位址。d類位址的低28位構成多播組id(group id),整個32位位址則成為組位址(group address)。
224.0.0.1為all-hosts組,224.0.0.2是all-routers組。
224.0.0.0~224.0.0.255之間的位址(224.0.0.0/24)稱為鏈路區域性(link-local)多播位址,是為低階拓撲發現和維護協議保留。
一般應用程式使用239.0.0.0~239.255.255.255之間的位址,稱作可管理地劃分範圍的ipv4多播空間(administratively scoped ipv4 multicast space)(rfc2365)。
static
const
auto multicast_group_address =
"239.255.43.21"
;static
const
unsigned
short multicast_group_port =
45454
;static
const
auto local_ip =
"192.168.1.222"
;
winsock.h與winsock2.h的一些巨集定義如ip_add_membership
使用了不同的值,因此須特別注意。這破問題我是在join gruop(setsockopt(sockfd, ipproto_ip, ip_add_membership...)
)始終失敗,後來檢查錯誤碼為10042 (wsaenoprotoopt),搜尋得知不可直接#include
, 而需要
#include #include #include #pragma comment(lib, "ws2_32.lib")
具體可參考info: header and library requirement when set/get socket options at the ipproto_ip level
無需多提,僅需建立udp socket,將資料報傳送至d類位址的某個約定好的埠即可。
struct sockaddr_in addr =
;addr.sin_family = af_inet;
addr.sin_port =
htons
(multicast_group_port)
;addr.sin_addr.s_addr =
inet_addr
(multicast_group_address)
;int addr_len =
sizeof
(addr)
;char host[
1024]=
;gethostname
(host,
1024);
int msgno =0;
char msg[
1024]=
;while
(true)
else
sleep
(1000);
}
必須繫結並設定出口網絡卡,否則會使用系統網絡卡列表的第乙個,有可能不是與其他裝置同乙個區域網的網絡卡。
int sockfd =
socket
(af_inet, sock_dgram,0)
;if(-
1== sockfd)
int reuse =1;
if(setsockopt
(sockfd, sol_socket, so_reuseaddr,
(const
char*)
&reuse,
sizeof
(reuse)
)<0)
struct sockaddr_in addr =
;addr.sin_family = af_inet;
addr.sin_port =
htons
(multicast_group_port)
;addr.sin_addr.s_addr = inaddr_any;
int addr_len =
sizeof
(addr)
;int ret =
bind
(sockfd,
(struct sockaddr*
)&addr,
sizeof
(struct sockaddr));
if(-1
== ret)
unsigned
long if_addr =
inet_addr
(local_ip)
;ret =
setsockopt
(sockfd, ipproto_ip, ip_multicast_if,
(const
char*)
&if_addr,
sizeof
(if_addr));
if(-1
== ret)
char host[
1024]=
;gethostname
(host,
1024);
int msgno =0;
char msg[
1024]=
;addr.sin_addr.s_addr =
inet_addr
(multicast_group_address)
;while
(true)
else
sleep
(1000);
}
非常簡單,網上的demo也大多針對這種情況。
建立udp socket,繫結inaddr_any、約定的埠,加入組播組,接收即可。
int ret =0;
int sockfd =
socket
(af_inet, sock_dgram,0)
;if(-
1== sockfd)
int reuse =1;
if(setsockopt
(sockfd, sol_socket, so_reuseaddr,
(const
char*)
&reuse,
sizeof
(reuse)
)<0)
struct sockaddr_in localaddr =
;localaddr.sin_family = af_inet;
localaddr.sin_port =
htons
(multicast_group_port)
;localaddr.sin_addr.s_addr =
/*inet_addr(local_ip)*/
htonl
(inaddr_any)
;ret =
bind
(sockfd,
(struct sockaddr*
)&localaddr,
sizeof
(struct sockaddr));
if(-1
== ret)
/*設定是否支援本地回環接收*/
/*int loopback = 1;
ret = setsockopt(sockfd, ipproto_ip, ip_multicast_loop, (const char *)&loopback, sizeof(loopback));
if (-1 == ret) */
struct ip_mreq ipmr =
;ipmr.imr_inte***ce.s_addr =
/*inet_addr(local_ip)*/
(inaddr_any)
;ipmr.imr_multiaddr.s_addr =
inet_addr
(multicast_group_address)
;int len =
sizeof
(ipmr)
;ret =
setsockopt
(sockfd, ipproto_ip, ip_add_membership,
(char*)
&ipmr, len);if
(-1== ret)
/* now just enter a read-print loop */
char msgbuf[msgbufsize]
;int nbytes =0;
localaddr.sin_addr.s_addr =
inet_addr
(multicast_group_address)
;while(1
) msgbuf[nbytes]=0
;puts
(msgbuf)
;}
有些不同,加入組播組時若依然使用inaddr_any,則核心預設使用網路裝置列表的第乙個裝置,有可能並不是該區域網。因此,需要將inaddr_any替換為local_ip,即本裝置與其他互相發現的裝置所在區域網的網絡卡ip。
ipmr.imr_inte***ce.s_addr =
inet_addr
(local_ip)
;
以上所有原始碼可在獲取。 Nacos系列 6 Nacos多網絡卡環境配置
實際生產環境,存在多網絡卡,此時使用nacos可能會存在ip不正確問題,針對此情況,nacos服務端ip,客戶端註冊ip應該怎麼配置?當前部署為單機環境nacos,版本1.3.2 找到nacos配置檔案 新增配置項nacos.inetutils.ip address,設定固定ip,啟動發現,ip已註...
windows多網絡卡使用改進
在前面的文章 windows下使用多網絡卡 中,提到了如何在windows下面使用多個網絡卡,但是在使用過程中,發現預設路由一段時間後就會被系統增加為2條,這樣就會導致問題出現。原因沒有深究,可能是因為路由器的設定,或者系統本身會定時重新通過dhcp獲取ip。所以,使用了取巧的辦法,改寫了之前的批處...
boost asio指定網絡卡加入多播組
有兩塊網絡卡,要指定加入特定網絡卡的多播組。看了一下boost asio文件,例子中沒有指定網絡卡 boost asio ip udp socket socket io service boost asio ip address multicast address boost asio ip add...