原文做者:aircrafthtml
原文連接:https://www.cnblogs.com/DOMLX/p/9614288.html前端
一.多播python
鍥子:有這麼一種狀況,網絡電臺可能須要同時向成千上萬的用戶傳輸相同的數據,若是用咱們之前講過的傳輸形式,每一個用戶都傳輸一次,這樣確定是不合理的。所以,就引入了多播技術來解決這個問題,它能夠同時向大量用戶發送相同數據。其基本原理是這樣的:有個多播組,只要加入這個組裏的全部客服端,服務端發送的數據它們都能收到,具體傳輸到多播組裏的每一個客戶是由路由完成的(若是路由器不支持多播或網絡堵塞,實現多播也會使用隧道技術)c++
多播的數據傳輸特色以下:
1,多播服務器端針對特定多播組,只需發送1次數據,該組內的全部全部客服端都能接收數據。
2,多播組數可在IP地址範圍內任意增長。編程
設置生存時間和加入多播組的方法
1,設置生存時間:只指服務端發送的數據包最遠能傳遞的距離,用整數表示,而且每通過1個路由器就減1,當爲0時,該數據包沒法再被傳遞,只能銷燬。所以,這個值設置過大將影響網絡流量。固然,設置太小也會沒法傳遞到目標(經過套接字可選項設置,示例代碼中有使用方法)。後端
2,加入多播組:也是經過套接字可選項設置,示例代碼中有使用方法,這裏只介紹多播組的結構體ip_mreq。服務器
struct ip_mreq
{
struct in_addr imr_multiaddr; //多播組的IP地址
struct in_addr imr_interface; //加入的客服端主機IP地址 網絡
}app
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define TTL 64 //數據包生存時間,即最多能夠傳遞通過第64個路由時銷燬 #define BUF_SIZE 30 void error_handling(char *message); int main(int argc, const char * argv[]) { int send_sock; struct sockaddr_in mul_adr; int time_live = TTL; FILE *fp; char buf[BUF_SIZE]; if (argc != 3) { printf("Usage : %s <GroupIp> <Port> \n", argv[0]); exit(1); } //基於UDP的多播 send_sock = socket(PF_INET, SOCK_DGRAM, 0); memset(&mul_adr, 0, sizeof(mul_adr)); mul_adr.sin_family = AF_INET; mul_adr.sin_addr.s_addr = inet_addr(argv[1]); mul_adr.sin_port = htons(atoi(argv[2])); //設置生存時間(除了這裏其它基本和UDP編寫同樣) setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&time_live, sizeof(time_live)); if((fp = fopen("/Users/app05/Desktop/test.txt", "r")) == NULL) error_handling("fopen() error"); while (!feof(fp)) //若是文件結束,則返回非0值,不然返回0 { fgets(buf, BUF_SIZE, fp); sendto(send_sock, buf, strlen(buf), 0, (struct sockaddr *)&mul_adr, sizeof(mul_adr)); sleep(1); //只是爲了加個傳輸數據時間間隔,沒有特殊意義 } fclose(fp); close(send_sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
接收者(receiver):機器學習
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 30 void error_handling(char *message); int main(int argc, const char * argv[]) { int recv_sock; int str_len; char buf[BUF_SIZE]; struct sockaddr_in adr; struct ip_mreq join_adr; //多播組結構體 if(argc != 3) { printf("Usage : %s <GroupIp> <Port> \n", argv[0]); exit(1); } recv_sock = socket(PF_INET, SOCK_DGRAM, 0); memset(&adr, 0, sizeof(adr)); adr.sin_family = AF_INET; adr.sin_addr.s_addr = htonl(INADDR_ANY); adr.sin_port = htons(atoi(argv[2])); if(bind(recv_sock, (struct sockaddr *)&adr, sizeof(adr)) == -1) error_handling("bind() error"); //加入多播組 join_adr.imr_multiaddr.s_addr = inet_addr(argv[1]); join_adr.imr_interface.s_addr = htonl(INADDR_ANY); setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&join_adr, sizeof(join_adr)); while (1) { str_len = recvfrom(recv_sock, buf, BUF_SIZE - 1, 0, NULL, 0);//只須要多播組IP地址,不關心本身主機地址 if(str_len < 0) break; buf[str_len] = 0; fputs(buf, stdout); } close(recv_sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
廣播在功能上和多播是同樣的,都是同時能夠向大量客戶傳遞數據。但他們在網絡範圍上有區別,多播能夠跨越不一樣的網絡,只要加入了多播組就能接收數據。但廣播只能向同一網絡中的主機傳輸數據。
廣播分爲:直接廣播與本地廣播,直接廣播sender的IP地址只需指定網絡地址,主機地址所有填255。這樣處在這個網絡地址裏的全部主機就能夠接收數據了。而本地廣播sender的IP地址寫255.255.255.255,這樣本地網絡全部主機就能夠接收數據了。
//將SO_BROADCAST可選項設置爲1就表示開啓了套接字廣播功能,默認是關閉的。
int bcast = 1;
setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (void *) &bcast, sizeof(bcast));
下面就多播的代碼示例稍做修改,本地廣播的示例以下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define TTL 64 //數據包生存時間,即最多能夠傳遞通過第64個路由時銷燬 #define BUF_SIZE 30 void error_handling(char *message); int main(int argc, const char * argv[]) { int send_sock; struct sockaddr_in mul_adr; int time_live = TTL; FILE *fp; char buf[BUF_SIZE]; if (argc != 3) { printf("Usage : %s <GroupIp> <Port> \n", argv[0]); exit(1); } //基於UDP的多播 send_sock = socket(PF_INET, SOCK_DGRAM, 0); memset(&mul_adr, 0, sizeof(mul_adr)); mul_adr.sin_family = AF_INET; mul_adr.sin_addr.s_addr = inet_addr(argv[1]); mul_adr.sin_port = htons(atoi(argv[2])); //設置生存時間(除了這裏其它基本和UDP編寫同樣) //setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&time_live, sizeof(time_live)); /*add:廣播修改處*/ //默認套接字是關閉廣播的,開啓以下: int so_brd = 1; //設置爲1就能夠開啓廣播 setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (void *)&so_brd, sizeof(so_brd)); if((fp = fopen("/Users/app05/Desktop/test.txt", "r")) == NULL) error_handling("fopen() error"); while (!feof(fp)) //若是文件結束,則返回非0值,不然返回0 { fgets(buf, BUF_SIZE, fp); sendto(send_sock, buf, strlen(buf), 0, (struct sockaddr *)&mul_adr, sizeof(mul_adr)); sleep(1); //只是爲了加個傳輸數據時間間隔,沒有特殊意義 } fclose(fp); close(send_sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
另外一個修改:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 30 void error_handling(char *message); int main(int argc, const char * argv[]) { int recv_sock; int str_len; char buf[BUF_SIZE]; struct sockaddr_in adr; //struct ip_mreq join_adr; //多播組結構體 if(argc != 2) { printf("Usage : %s <GroupIp> <Port> \n", argv[0]); exit(1); } recv_sock = socket(PF_INET, SOCK_DGRAM, 0); memset(&adr, 0, sizeof(adr)); adr.sin_family = AF_INET; adr.sin_addr.s_addr = htonl(INADDR_ANY); adr.sin_port = htons(atoi(argv[1])); if(bind(recv_sock, (struct sockaddr *)&adr, sizeof(adr)) == -1) error_handling("bind() error"); //加入多播組 //join_adr.imr_multiaddr.s_addr = inet_addr(argv[1]); //join_adr.imr_interface.s_addr = htonl(INADDR_ANY); //setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&join_adr, sizeof(join_adr)); while (1) { str_len = recvfrom(recv_sock, buf, BUF_SIZE - 1, 0, NULL, 0);//只須要多播組IP地址,不關心本身主機地址 if(str_len < 0) break; buf[str_len] = 0; fputs(buf, stdout); } close(recv_sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
最後說一句啦。本網絡編程入門系列博客是連載學習的,有興趣的能夠看我博客其餘篇。。。。c++ 網絡編程課設入門超詳細教程 ---目錄
好了今天對網絡編程的學習就到這裏結束了,小飛機我要撤了去吃飯了。,,,不少人大學都很迷茫不知道學點什麼好,,,,,管他的,想那麼多幹嗎,先學了再說,對技術若有偏見,那麼你的領域就侷限於此了---《一專多精》
參考博客:https://blog.csdn.net/u010223072/article/details/48269213
參考書籍:《TCP/IP 網絡編程 --尹聖雨》
如有興趣交流分享技術,可關注本人公衆號,裏面會不按期的分享各類編程教程,和共享源碼,諸如研究分享關於c/c++,python,前端,後端,opencv,halcon,opengl,機器學習深度學習之類有關於基礎編程,圖像處理和機器視覺開發的知識