廣播和多播僅應用于UDP。TCP是一個面向連接的協議,TCP一定是點對點的,一點是兩個主機來建立連接的,TCP肯定是單播。只有UDP才會使用廣播和組播。
如下示例實現一個UDP多對多的組播通信,進程中有收、發兩個線程,分別表示往組播發送、接收數據。
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>// 組播地址必須是D類地址,224.0.0.0~239.255.255.255
#define GROUP_IP "239.0.0.1"
#define GROUP_PORT 8888
#define MAX_MESSAGE 128void *sender(void *arg) {int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {printf("Sender alloc socket failed! %s", strerror(errno));pthread_exit(NULL);}struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(GROUP_IP);addr.sin_port = htons(GROUP_PORT);while(1) {char message[MAX_MESSAGE];printf("Enter message to send: ");fgets(message, MAX_MESSAGE, stdin);sendto(sockfd, message, strlen(message), 0, (struct sockaddr *)&addr, sizeof(addr));}close(sockfd);pthread_exit(NULL);
}void *receiver(void *arg) {int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {printf("Receiver alloc socket failed! %s", strerror(errno));pthread_exit(NULL);}struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(GROUP_IP);addr.sin_port = htons(GROUP_PORT);struct ip_mreq mreq;mreq.imr_multiaddr.s_addr = inet_addr(GROUP_IP);mreq.imr_interface.s_addr = htonl(INADDR_ANY);/* 加入組播 */int ret = setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));if (ret < 0) {printf("IP_ADD_MEMBERSHIP failed! %s", strerror(errno));pthread_exit(NULL);}/* 設置端口復用,多個進程監聽同一端口 */ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &mreq, sizeof(mreq));if (ret < 0) {printf("SO_REUSEADDR failed! %s", strerror(errno));pthread_exit(NULL);}ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));if (ret < 0) {printf("Bind failed! %s", strerror(errno));pthread_exit(NULL);}char message[MAX_MESSAGE];struct sockaddr_in sender_addr;socklen_t sender_len = sizeof(sender_addr);while(1) {recvfrom(sockfd, message, MAX_MESSAGE, 0, (struct sockaddr *)&sender_addr, &sender_len);printf("Received message from %s:%d - %s\n", inet_ntoa(sender_addr.sin_addr), ntohs(sender_addr.sin_port), message);}close(sockfd);pthread_exit(NULL);
}int main() {pthread_t threadA, threadB;pthread_create(&threadA, NULL, sender, NULL);pthread_create(&threadB, NULL, receiver, NULL);pthread_join(threadA, NULL);pthread_join(threadB, NULL);return 0;
}
運行結果如下:
使用任意節點發送消息,其它的節點都能收到。