IPv4接收端代码(windows)
#include <stdio.h> #include <winsock2.h> #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") #define BUFLEN 255 #define GROUP_ADDR "229.0.0.211" #define GROUP_PORT 12345 int main(int argc, char **argv) { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); struct sockaddr_in peeraddr; int sockfd; char recmsg[BUFLEN + 1]; unsigned int socklen; struct ip_mreq mreq; /* 创建 socket 用于UDP通讯 */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { printf("socket creating err in udptalk\n"); exit(1); } mreq.imr_multiaddr.s_addr = inet_addr(GROUP_ADDR); mreq.imr_interface.s_addr = htonl(INADDR_ANY);//本地ip地址 /* 把本机加入组播地址,即本机网卡作为组播成员,只有加入组才能收到组播消息 */ if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) == -1) { perror("setsockopt"); exit(-1); } socklen = sizeof(struct sockaddr_in); memset(&peeraddr, 0, socklen); peeraddr.sin_family = AF_INET; peeraddr.sin_addr.s_addr = htonl(INADDR_ANY); peeraddr.sin_port = htons(GROUP_PORT); /* 绑定自己的端口和IP信息到socket上 */ if (bind(sockfd, (struct sockaddr *) &peeraddr, sizeof(struct sockaddr_in)) == -1) { printf("Bind error\n"); exit(0); } /* 循环接收网络上来的组播消息 */ for (;;) { //bzero(recmsg, BUFLEN + 1); memset(recmsg, 0, sizeof(BUFLEN + 1)); int n = recvfrom(sockfd, recmsg, BUFLEN, 0, (struct sockaddr *) &peeraddr, &socklen); if (n < 0) { printf("recvfrom err in udptalk!\n"); exit(4); } else { /* 成功接收到数据报 */ recmsg[n] = 0; printf("peer:%s\r\n", recmsg); } } closesocket(sockfd); WSACleanup(); }
IPv4发送端代码(windows)
#include <stdio.h> #include <winsock2.h> #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") int main(int argc, char** argv) { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); int n = 0; // 注意, 这个n值很重要, 下面我会讲到 setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&n, sizeof(n)); sockaddr_in addr; addr.sin_addr.S_un.S_addr = inet_addr("229.0.0.211");//像组播地址发送消息 addr.sin_family = AF_INET; addr.sin_port = htons(12345); static int i = 0; while (1) { char buf[100] = { 0 }; sprintf(buf, "blablablabla:%d", i++); sendto(sock, buf, strlen(buf) + 1, 0, (sockaddr*)&addr, sizeof(sockaddr)); Sleep(500); } closesocket(sock); WSACleanup(); return 0; }
IPv6发送端代码(linux)
IPv6多播代码,用于linux下,window下差不多
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define MULTICAST_ADDR "ff14::2:e" // 多播组地址,这里不能用"ff02::1"等多播组(否则接收端无法接收到数据,原因未知,我草,这个问题找了好久好久,基本上网上好多代码都用ff02::1这个多播组,然后接收方死活收不到组播数据) //#define MULTICAST_ADDR "ff02::1" #define PORT 12345 // Port number int main() { int sockfd; struct sockaddr_in6 multicast_addr; char message[] = "Hello, multicast11111!"; // Create socket sockfd = socket(AF_INET6, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket"); exit(EXIT_FAILURE); } // Set socket options for multicast int enable = 1; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &enable, sizeof(enable)) < 0) { perror("setsockopt"); exit(EXIT_FAILURE); } // Set multicast group address and port memset(&multicast_addr, 0, sizeof(multicast_addr)); multicast_addr.sin6_family = AF_INET6; multicast_addr.sin6_port = htons(PORT); if (inet_pton(AF_INET6, MULTICAST_ADDR, &(multicast_addr.sin6_addr)) <= 0) { perror("inet_pton"); exit(EXIT_FAILURE); } while(1) { // Send multicast packet if (sendto(sockfd, message, strlen(message), 0, (struct sockaddr*)&multicast_addr, sizeof(multicast_addr)) < 0) { perror("sendto"); exit(EXIT_FAILURE); } } printf("Multicast packet sent.\n"); close(sockfd); return 0; }
IPv6接收端代码(linux)
这里列举linux下的组播接收端的代码,windows类似,需要加WSAStartup,另外需要将bind那里不同,linux需要绑定多播地址,而windows需要绑定本机的一个地址,注意看下面bind那里的注释
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/types.h> #include <sys/socket.h> #include <errno.h> #include <netdb.h> #define MAX_BUFFER_SIZE 1024 #define MULTICAST_ADDR "ff02::1" int main() { int sockfd; struct addrinfo *multicast_addr = NULL; char buffer[MAX_BUFFER_SIZE]; // Create socket sockfd = socket(AF_INET6, SOCK_DGRAM, 0); if (sockfd < 0) { perror("Failed to create socket"); exit(EXIT_FAILURE); } struct addrinfo hint = {0}; struct addrinfo *info = NULL; hint.ai_family = AF_INET6; hint.ai_socktype = SOCK_DGRAM; int err = getaddrinfo("fe80::d609:e8da:7b4d:7f42",NULL,&hint,&info);//fe80::d609:e8da:7b4d:7f42 是本机的一个本机链接地址 if(err != 0) { perror("getaddrinfo"); exit(1); } struct sockaddr_in6 *addr = (struct sockaddr_in6*)info->ai_addr; inet_pton(AF_INET6,MULTICAST_ADDR,&addr->sin6_addr);//如果是windows,需要将这句注释掉,本机是绑定本机地址,而不是绑定多播地址 // addr->sin6_addr = in6addr_any; addr->sin6_port = htons(12345); if(bind(sockfd,(struct sockaddr*)addr,info->ai_addrlen) != 0) { close(sockfd); printf("bind error,errno:%d\n",errno); //perror("bind"); exit(1); } if(getaddrinfo(MULTICAST_ADDR,NULL,&hint, &multicast_addr) != 0) { close(sockfd); perror("getaddrinfo"); exit(1); } struct ipv6_mreq mreq; memset( &mreq, 0, sizeof(mreq) ); memcpy( &mreq.ipv6mr_multiaddr, &((struct sockaddr_in6 *) multicast_addr->ai_addr)->sin6_addr, sizeof(mreq.ipv6mr_multiaddr) ); mreq.ipv6mr_interface = 0; // 2 happens to be the interface ID; I've tried other values here freeaddrinfo(multicast_addr); if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq) ) != 0 ) { close(sockfd); perror( "IPV6_JOIN_GROUP" ); exit( 1 ); } printf("join group success\n"); // Receive multicast packets while (1) { ssize_t num_bytes = recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, 0); if (num_bytes < 0) { perror("Failed to receive packet"); exit(EXIT_FAILURE); } // Process received packet // ... // Print received data printf("Received: %.*s\n", (int)num_bytes, buffer); } // Close socket close(sockfd); return 0; }
参考
https://blog.csdn.net/u010429831/article/details/122495698