多播基于udp,让路由器复制数据包传递基本和udp 程序一样不同的地方:对于发送者重要的 ,1 发送数据不再直接发送到对端,而是发送到多播地址, 但端口还是对端的端口(否则对端套接字无法接受到数据),这样通过路由器复制再转发, 对端recvfrom 的ip 将是路由器2 多播ttl (默认1, 还是修改一下保险一些); send_addr.sin_addr.s_addr = inet_addr(ipaddr); //多播地址 send_addr.sin_port = htons(port); //对端端口 DWORD ttl = 64; //设置多播ttl,默认是1 有可能不太够用 setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,(char*)&ttl,sizeof(ttl));对于接受方 :1 由于是多播,由路由器复制并传递, 所以接受到的ip地址一般来说是路由器.2 需要bind一下port 用于接受数据,再来就是socket需要通过 setsockopt 加入多播组,否则无法接受多播组的信息以上2点代码示意: // bind ip,port , 否则无法接受数据 if (bind(sock, (SOCKADDR*)&local_addr, sizeof(local_addr)) == SOCKET_ERROR){ print_error(WSAGetLastError()); return 0; } //多播结构 IP_MREQ join_addr; join_addr.imr_interface.s_addr = INADDR_ANY; //加入多播的主机,一般来说就是本机 join_addr.imr_multiaddr.s_addr = inet_addr(ip); //需要加入的多播地址 //通过 IP_ADD_MEMBERSHIP 让socket 加入多播 setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&join_addr, sizeof(join_addr));全部代码:multi_sender.c WSADATA wsadata; WSAStartup(MAKEWORD(2, 2), &wsadata); SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); char ipaddr[16]; int port = 0; scanf(" %s %d", ipaddr,&port); SOCKADDR_IN send_addr; printf(“ip:%s\n”, ipaddr); memset(&send_addr, 0, sizeof(send_addr)); send_addr.sin_addr.s_addr = inet_addr(ipaddr); //发往多播地址 send_addr.sin_port = htons(port); //接受方的端口 send_addr.sin_family = AF_INET; DWORD ttl = 64; setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,(char*)&ttl,sizeof(ttl)); char buf[100] = “fuck you”; for (int i = 0; i < 3; ++i){ sendto(sock, buf, strlen(buf), 0, (SOCKADDR*)&send_addr, sizeof(send_addr)); Sleep(1000); } closesocket(sock); WSACleanup();mutli_recver.c char ip[16]; unsigned short port = 0; scanf(" %s %hd", ip, &port); WSADATA wsadata; WSAStartup(MAKEWORD(2, 2), &wsadata); SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); SOCKADDR_IN local_addr; memset(&local_addr, 0, sizeof(local_addr)); local_addr.sin_addr.s_addr = INADDR_ANY; local_addr.sin_family = AF_INET; local_addr.sin_port = htons(port); //接受的端口号 if (bind(sock, (SOCKADDR*)&local_addr, sizeof(local_addr)) == SOCKET_ERROR){ print_error(WSAGetLastError()); return 0; } //加入多播的结构 IP_MREQ join_addr; join_addr.imr_interface.s_addr = INADDR_ANY; //本机所有接口 join_addr.imr_multiaddr.s_addr = inet_addr(ip); //加入多播地址 //通过IP_ADD_MEMBERSHIP 加入多播组 setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&join_addr, sizeof(join_addr)); char buf[100]; SOCKADDR_IN client_addr; int cli_len = sizeof(client_addr); memset(&client_addr, 0, cli_len); int n = 0; while (1){ cli_len = sizeof(client_addr); n = recvfrom(sock, buf, sizeof(buf), 0, (SOCKADDR*)&client_addr, &cli_len); if (n == 0){ puts(“peer closed”); break; } else if (n == SOCKET_ERROR){ print_error(WSAGetLastError()); break; } else { buf[n] = 0; printf(“buf:%s, ip from : %s ,port:%d\n”, buf,inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); } } WSACleanup();