linux網絡編程(組播)


組播        
    1. 分組
       每個D類IP地址就是一個組,組播實現原理:
       接收 -- 加入一個組
       發送 -- 向一個組(目標IP地址為組播地址)發送數據包  
       
    2. 組播地址(IP地址和網卡地址)
       IP地址: D類地址 ,高位固定為1110,范圍: 224.0.0.0-239.255.255.255
       網卡地址: 前24bit固定為01-00-5e, 最后23bit是D類IP地址的后23bit直接映射下來 -- 僅僅正對於以太網
       
    3. 接收流程
       (1) 創建套接字
           sockfd = socket(AF_INET, SOCK_DGRAM, 0);
           
       (2) 加入組
           struct ip_mreq mreq;
           mreq.imr_multiaddr.s_addr = inet_addr(argv[1]);  // "224.10.10.1"
           mreq.imr_interface.s_addr = INADDR_ANY;
           
           ret = setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
           
       (3) 綁定IP地址和端口
           struct sockaddr_in addr;
           
           bzero(&addr, sizeof(addr));
           addr.sin_family = AF_INET;
           addr.sin_port = htons(port);
           addr.sin_addr.s_addr = inet_addr(ip);
           // addr.sin_addr.s_addr = INADDR_ANY;
           
           ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
           
       (4) 接收
           struct sockaddr_in peer_addr;
           socklen_t addrlen = sizeof(peer_addr);
           
           ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&peer_addr, &addrlen);
           
       (3) 關閉
           close(sockfd);
           
       
    4. 發送流程
       (1) 創建套接字
           sockfd = socket(AF_INET, SOCK_DGRAM, 0);
           
       (2) 發送
           struct sockaddr_in muticast_addr;
           
           bzero(&muticast_addr, sizeof(muticast_addr));
           muticast_addr.sin_family = AF_INET;
           muticast_addr.sin_port = htons(port);
           muticast_addr.sin_addr.s_addr = inet_addr(一定填多播(224.10.10.1));
           
           ret = sendto(sockfd, buf, len, 0, (struct sockaddr *)&broad_addr, sizeof(broad_addr));
           
       (3) 關閉

           close(sockfd);


組播(代碼)

一、發送端

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <strings.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// ./send 224.0.0.1 8888
int main(int argc, const char *argv[])
{
int ret;
int sockfd;
char packet[1024];
struct sockaddr_in muti_addr;

if (argc < 3){
fprintf(stderr, "Usage: %s <broadcast ip> <port>\n", argv[0]);
exit(EXIT_FAILURE);
}

// 1. 創建報文套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd){
perror("Fail to socket.");
exit(EXIT_FAILURE);
}

// 2. 通過多播地址發送數據包到指定端口
bzero(&muti_addr, sizeof(muti_addr));
muti_addr.sin_family = AF_INET;
muti_addr.sin_port = htons(atoi(argv[2]));
muti_addr.sin_addr.s_addr = inet_addr(argv[1]);

while (1){
putchar('\n');
putchar('>');
fgets(packet, sizeof(packet), stdin);
packet[strlen(packet) - 1] = '\0';

ret = sendto(sockfd, packet, strlen(packet), 0, (struct sockaddr *)&muti_addr, sizeof(muti_addr));
if (-1 == ret){
perror("Fail to sendto.");
break;
}

if (strcmp(packet, "quit") == 0){
break;
}
}

// 3. 關閉套接字
close(sockfd);

return 0;
}

二、接收端

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <strings.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// ./recv 192.168.2.255 8888
int main(int argc, const char *argv[])
{
int ret;
int sockfd;
char packet[1024];
struct sockaddr_in addr;
struct ip_mreq mreq;
struct sockaddr_in peer_addr;
socklen_t addrlen = sizeof(peer_addr);

if (argc < 3){
fprintf(stderr, "Usage: %s <broadcast ip> <port>\n", argv[0]);
exit(EXIT_FAILURE);
}

// 1. 創建報文套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd){
perror("Fail to socket.");
exit(EXIT_FAILURE);
}
//加入組
mreq.imr_multiaddr.s_addr = inet_addr(argv[1]);
mreq.imr_interface.s_addr = INADDR_ANY;
ret = setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
if(-1 == ret){
perror("fail to setsockopt");
exit(EXIT_FAILURE);
}
// 2. 綁定廣播地址和端口
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[2]));
// broad_addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_addr.s_addr = INADDR_ANY;

ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
if (-1 == ret){
perror("Fail to bind.");
exit(EXIT_FAILURE);
}

while (1){
// 3. 接收
ret = recvfrom(sockfd, packet, sizeof(packet), 0, (struct sockaddr *)&peer_addr, &addrlen);
if (-1 == ret){
perror("Fail to recvfrom.");
break;
}
packet[ret] = '\0';

printf("---------------------------------------\n");
printf("ip : %s\n", inet_ntoa(peer_addr.sin_addr));
printf("port : %d\n", ntohs(peer_addr.sin_port));
printf("recv(%d) : %s\n", ret, packet);
printf("---------------------------------------\n");
if (strcmp(packet, "quit") == 0){
break;
}
}

// 4. 關閉套接字
close(sockfd);

return 0;
}



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com