網路編程練習題---利用UDP協議實現組播通信

来源:https://www.cnblogs.com/fly-home/p/18231570
-Advertisement-
Play Games

目錄題目解析代碼實現 題目 解析 由於該題需要實現組播通信,所以我們需要將套接字文件句柄設置為組播屬性,並將需要通信的用戶端IP地址,加入組中。 由於組播通信需要實現一對多發送消息,所以還需要將套接字文件句柄的廣播屬性一併開啟。 由於該題實現過程使用到了線程相關函數介面,所以編譯時需要帶上 “-pt ...


目錄

題目

image

解析

  1. 由於該題需要實現組播通信,所以我們需要將套接字文件句柄設置為組播屬性,並將需要通信的用戶端IP地址,加入組中。
  2. 由於組播通信需要實現一對多發送消息,所以還需要將套接字文件句柄的廣播屬性一併開啟。
  3. 由於該題實現過程使用到了線程相關函數介面,所以編譯時需要帶上 “-pthread“ 選項

代碼實現

/********************************************************************************
*
*	file name:	udp_group.c
*	author	 :  [email protected] 
*	date	 :  2024/06/04
*	function :  該案例是掌握UDP協議的組播通信方式
* 	note	 :  
*				想要實現組間通信,只需要對本地地址進行修改後,可實現組間通信,即一個用戶
*				發送的消息,組間所有用戶都能收到
*   version  :
*
*	CopyRight (c)  2023-2024   [email protected]   All Right Reseverd 
*
* ******************************************************************************/
/****************************頭文件*********************************************/
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>

/****************************全局變數*********************************************/
int udp_socket;								//用於存儲套接字文件的句柄

/****************************巨集*********************************************/
#define PORT 	  60000 					//用戶端運行進程的埠號
#define IP_HOST   "192.168.64.94"			//用戶端本地IP地址
#define	IP_GROUP  "226.66.66.66"			//組播通信IP地址


/********************************************************************************
*
*	name	 :	recv_time
*	function :  實現獲取當前系統時間,並對獲取值進行固定格式的處理,獲得更好的顯示效果
*	param :  
*				none
*				
*	retval	 :  調用成功返回處理後的當前系統時間
*	author	 :  [email protected] 
*	date	 :  2024/06/04
* 	note	 : 
*				輸出時間的格式固定為:"X年 X月 X日 星期X XX:XX:XX",可根據需要進行修改
*   version  :
* 	
* *****************************************************************************/
char *recv_time()
{
	//定義一個字元指針,用於存儲獲取的當前系統時間值
	char *buf =(char *)calloc(1,128);
	//定義一個字元數組,用於優化後的星期值
	char wekday[10];
	//利用time()獲取當前系統時間,並將返回值存儲起來
	time_t systime = time(NULL);
	//利用localtime()對獲取值進行處理,並將處理後的數據寫入目標文件中
	struct tm *systimep = localtime(&systime);
	systimep->tm_year += 1900;
	systimep->tm_mon += 1;
	//對獲取星期數值進行判斷,併進行美觀優化
	if(systimep->tm_wday == 1)
		{
			strcpy(wekday, "一");
		}
		else if(systimep->tm_wday == 2) 
		{
			strcpy(wekday, "二");
		}
		else if(systimep->tm_wday == 3) 
		{
			strcpy(wekday, "三");
		}
		else if(systimep->tm_wday == 4) 
		{
			strcpy(wekday, "四");
		}
		else if(systimep->tm_wday == 5) 
		{
			strcpy(wekday, "五");
		}
		else if(systimep->tm_wday == 6) 
		{
			strcpy(wekday, "六");
		}
		else if(systimep->tm_wday == 7) 
		{
			strcpy(wekday, "日");
		}

		//將獲取值按固定格式寫入緩衝區中
		sprintf(buf, "%d年 %d月 %d日 星期%s %d:%d:%d", systimep->tm_year,
				systimep->tm_mon,
				systimep->tm_mday,
				wekday,
				systimep->tm_hour,
				systimep->tm_min,
				systimep->tm_sec);

		return buf;
}

/********************************************************************************
*
*	name	 :	recv_msg
*	function :  接收信息線程的任務函數
*	param :  
*				none
*				
*	retval	 :  none
*	author	 :  [email protected] 
*	date	 :  2024/06/04
* 	note	 :  
*				對應填寫的IP地址,可以通過程式開頭的巨集定義進行修改
*   version  :
* 	
* *****************************************************************************/
void *recv_msg(void *arg)
{
	//將該線程的屬性設置為分離屬性,防止線程結束後變為僵屍線程
	pthread_detach(pthread_self());
	//綁定伺服器的埠和地址
	struct sockaddr_in  host_addr;

	host_addr.sin_family 		= AF_INET; 						//協議族,UDP協議固定填寫該巨集定義
	host_addr.sin_port   		= htons(PORT);					//想要接收信息進程的埠號
	host_addr.sin_addr.s_addr   = htonl(INADDR_ANY);			//本地地址,填寫該巨集定義代表任意網口都可以接收值

	bind(udp_socket,(struct sockaddr *)&host_addr, sizeof(host_addr));

	//調用recvfrom等待接收數據,並且接收客戶端的網路信息
	char buf[128] = {0};
	struct sockaddr_in  client;
	socklen_t client_len = sizeof(client);

	//定義一個字元數組用於存儲系統時間
	char *recvtime = (char *)calloc(128,1);
	while(1)
	{
		recvfrom(udp_socket,buf,sizeof(buf), 0 ,(struct sockaddr *)&client,&client_len); //函數標識定義為預設屬性,即會阻塞
		recvtime = recv_time();
		if(client.sin_addr.s_addr == inet_addr(IP_HOST))
		{
			bzero(buf,sizeof(buf));
			continue;
			
		}
			printf("[%s] (%s): %s\n",inet_ntoa(client.sin_addr),recvtime,buf);
		bzero(buf,sizeof(buf));
	}
}

/********************************************************************************
*
*	name	 :	send_msg
*	function :  發送信息線程的任務函數
*	param :  
*				none
*				
*	retval	 :  none
*	author	 :  [email protected] 
*	date	 :  2024/06/04
* 	note	 :  
*				對應填寫的IP地址,可以通過程式開頭的巨集定義進行修改
*   version  :
* 	
* *****************************************************************************/
void *send_msg(void *arg)
{
	//將該線程的屬性設置為分離屬性,防止線程結束後變為僵屍線程
	pthread_detach(pthread_self());
	
	//向目標主機發送消息,需要設置目標埠和目標地址
	char buf[128] = {0};
	
	struct sockaddr_in  dest_addr;
	dest_addr.sin_family 		= AF_INET; 						//協議族,是固定的
	dest_addr.sin_port   		= htons(PORT);					//伺服器運行進程的埠號,必須轉換為網路位元組序
	dest_addr.sin_addr.s_addr   = inet_addr(IP_GROUP);			//要發送對象的IP地址,必須轉換為點分十進位字元串形式

	while(1)
	{
		//阻塞等待獲取用戶從鍵盤輸入的信息
		scanf("%s", buf);
		//發送獲取到的用戶輸入信息
		sendto(udp_socket,buf,strlen(buf),0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
	}

	
}

int main(int argc,char *argv[])
{
	
	//創建UDP套接字,並存儲套接字文件的句柄            
	udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
	if (udp_socket == -1)
	{
		fprintf(stderr, "udp socket error,errno:%d,%s\n",errno,strerror(errno));
		exit(1);
	}

	//將套接字文件的廣播屬性設置為開啟
	int flag = 1;
	socklen_t flag_len = sizeof(flag);
	setsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST, (void *)&flag, flag_len);

	//將套接字文件的組播屬性設置為開啟
	struct ip_mreqn ip_grop;
	ip_grop.imr_multiaddr.s_addr = inet_addr(IP_GROUP);//設置組播地址
	ip_grop.imr_address.s_addr = inet_addr(IP_HOST); //設置要加入組的本地地址
	ip_grop.imr_ifindex = 0;								 //設置為預設屬性,由系統分配埠

	socklen_t ip_len = sizeof(ip_grop);
	setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&ip_grop, ip_len);
	
	//創建兩個線程,分別用於發送數據和接受數據
	pthread_t send;
	pthread_t recv;
	pthread_create(&send, NULL, send_msg, NULL);
	pthread_create(&recv, NULL, recv_msg, NULL);

	//關閉主線程
	pthread_exit(NULL);

	return 0;

}


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 寫了個盯盤小工具,最近發現很多炒股的小伙伴,上班期間看手機頻繁是不是影響不好?電腦上打開交易軟體,那影響是不是更不好?所以我就寫了個小工具,給大家“摸魚”用。雖然是摸魚用,但是平常丟一邊,或者你自己改造下代碼,寫個死迴圈在控制台裡面刷新等等,或者輸出到VS的輸出欄裡面等等,都行,也不會影響你工作,還 ...
  • 前言:最近幾天有好幾個小伙伴玩WPF,遇到不同頁面,不知道要怎麼傳遞消息。於是,我今天就來演示一個事件聚合器的玩法,採用prism框架來實現。作為福利,內容附帶了主頁面打開對話框時候直接通過參數傳遞消息的一個小例子,具體請自行圍觀。 以下內容,創建wpf項目以及引用prism和實現依賴註入等細節,可 ...
  • 本文分享自天翼雲開發者社區《linux各個目錄的作用》,作者:技術小白 /bin/:存放系統命令的目錄,普通用戶和超級用戶都可以執行,不過放在/bin下的命令在單用戶模式下也可以執行; /sbin/:保存和系統環境設置相關的命令,只有超級用戶可以使用這些命令進行系統環境設置,但是有些命令可以允許普通 ...
  • 目錄傳輸控制協議(TCP)TCP協議 的特點TCP協議的可靠性TCP的連接機制 傳輸控制協議(TCP) 傳輸控制協議(TCP)用於作為包交換電腦通信網路中的主機以及此類網路的互連繫統中的高度可靠的主機對主機協議。 TCP協議 的特點 TCP協議是面向連接的,端到端可靠的協議,該協議被設計適應支持多 ...
  • 目錄題目一解析代碼實現題目二:解析代碼實現tcp_client.ctcp_server.c 題目一 設計程式實現解析www.baidu.com的功能變數名稱,把獲取到的百度的IP地址全部輸出到終端並驗證是否正確。 解析 主機打算響應某個網站的網路請求,但是只知道網站功能變數名稱是無法通信的,需要對功能變數名稱進行地址解析, ...
  • 移植 使用預設模板工程新建一個RT-Thread項目,BSP版本為1.1.1 打開RT-Thread Settings,點擊右側箭頭按鈕進入詳細頁,在硬體欄開啟以下幾個配置選項(LCD、觸摸屏、demo) 此時,打開board文件夾,發現下麵會有一個lvgl的目錄,package目錄下會有LVGL和 ...
  • 目錄題目分析代碼結果 題目 小組實現,小組中的每位成員都需要設計程式,要求程式可以加入到一個多播組中並等待伺服器發送數據包,並且程式還需要具有發送功能,如果收到數據包則把消息內容輸出到終端, 消息內容格式 [消息來源IP 消息時間 ] : 消息內容 分析 1.發送端需設置套接字的廣播屬性,使用set ...
  • 目錄題目分析代碼結果 題目 設計程式實現解析www.baidu.com的功能變數名稱,把獲取到的百度的IP地址全部輸出到終端並驗證是否正確。 分析 1.通過目標功能變數名稱獲取目標IP地址對應的網路位元組序(需強轉為對應的類型),使用gethostbyname()函數; 2.把獲取的網路位元組序轉換為點分十進位的IP地 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...