c/c++11封裝UDP,支持ipv4和ipv6,支持接收和發送


更新日志

11/06/2021

  • 1.增加IPV6
  • 2.ipv6通過windows10初步測試
  • 3.ipv6包括: 接收和發送
  • 5.增加錯誤代碼接口
  • 6.本機IPv6截圖
  • 7.編譯通過截圖
  • 8.ipv6測試結果

30/05/2021

1.增加IPv6,待測
2.全部改為Unicode編碼, 無簽名

23-05-2021

1.模塊內部增加優化

15/12/2020

  1. cmake重新配置,改為支持modern cmake
  2. 創建cmake文件夾,並創建spdlog.cmake文件
  3. 類的成員函數和成員變量重命名

11/06/2021

  1. 增加IPV6
  2. ipv6通過windows10初步測試
    3.ipv6包括: 接收和發送
    5.增加錯誤代碼接口

30/05/2021

1.增加IPv6,待測
2.全部改為Unicode編碼, 無簽名

簡介

  • 1.這是一個使用C++11語法封裝的UDP,包括: ipv4 和 ipv6
  • 2.ipv4支持: 單播、組播、廣播; linux + windows10測試通過,接收和發送均成功
  • 3.ipv6通過windows10初步測試。收發均成功; 組播待測
  • 5.支持接收和發送
  • 6.使用cmake管理的項目
  • 7.提供了調用范例
  • 8.Linux支持仔細測試,最近比較忙。 后期更新
  • 9.歡迎留言指導

接口分類

針對使用場景: 初始化, 發送, 接收, 關閉, 如果不接收, 則只有3個接口。 接口函數返回值后面再更新

使用

接收

接收需要重載 iudp.h中的類irecv_data的on_recv_data_函數。 on_recv_data_原型如下:

		///  --------------------------------------------------------------------------------
		///  @brief: 	接收函數,
		///  @param:	const unsigned char * pdata_recv - 接收的數據
		///  @param:	const unsigned int recv_data_len - 接收數據長度
		///  @return:	void	
		/// 			
		///  --------------------------------------------------------------------------------
		virtual void on_recv_data_(const unsigned char *pdata_recv, const unsigned int recv_data_len) = 0;

接收繼承范例

  • 你可以在 example/main.cc 中找到下面的代碼
  • my_udp繼承了類irecv_data類, 並實現函數on_recv_data_
class my_udp : public irecv_data
{
public:
	/// ...... 
	/// ...... 

	/// you must override this function to recv data
	void on_recv_data_(const unsigned char *pdata_recv, const unsigned int recv_data_len)
	{
		/// -------------------------------------------------------------------------------
		/// 1. recv data
		std::cout << "\n --------------AAAAAA data length = " << recv_data_len << "\n";
		for (unsigned int i = 0; i < recv_data_len; i++)
		{
			if (i == 10)
				std:: cout << "\n";

			std::cout << pdata_recv[i] << ", ";
		}
		
		std::cout << "\n";
	}

	/// .... 

當接收到數據,底層會調用該函數

接收要注意

  • 如果需要接收數據,接口類 iudp 的接口 init_ 的第二個參數需要傳遞繼承自 接口類irecv_dataon_recv_data_ 接口
  • 如果不接收數據,接口類 iudp 的接口 init_ 的第二個參數傳遞 NULL(或nullptr)即可, 也不需要繼承 接口類irecv_data

接口類iudp

  • iudp提供了udp的初始化、發送數據和關閉,提供了接口 error_id_() 獲取錯誤代碼
  • 接口返回值詳見代碼(代碼寫的比較詳細了)
  • 接口盡量設計的簡潔

代碼

/// ----------------------------------------------------------------------------
	/// @brief: UDP接口類
	/// ----------------------------------------------------------------------------
	class iudp
	{
	public:
		virtual ~iudp(){}

		/// ------------------------------------------------------------
		/// @brief:初始化
		/// @param: const udp_param & param - 初始化參數
		/// @param: irecv_data * pfunc_recv - 接收對象
		/// @return: int
		/// 			0 - 成功
		///				-1 - 失敗,param.socket_version_ 傳遞錯誤
		/// --------------------------------------------------------------
		///			ipv4和ipv6錯誤, 請調用error_id_()獲取錯誤代碼
		///				1 - 失敗, 端口為0
		///				2 - 失敗,  套接字創建失敗
		///				3 - 失敗,設置發送超時失敗
		///				5 - 失敗, 設置接收超時失敗
		///				6 - 失敗, 設置發送緩沖失敗
		///				7 - 失敗,設置接收緩沖失敗
		///				8 - 失敗,設置地址寵用失敗
		///				9 - 失敗, 綁定套接字失敗
		///				10 、11、12 - 失敗, 設置套接字 組播屬性失敗
		///				13 - 失敗,設置廣播失敗
		///				15 - 失敗,param._cast_type參數值傳遞錯誤
		/// ------------------------------------------------------------
		virtual int init_(const udp_param& param, irecv_data* pfunc_recv /* = nullptr */) = 0;
	

		/// ------------------------------------------------------------
		/// @brief:發送數據
		/// @param: const unsigned char * psend - 待發送數據
		/// @param: const unsigned int len_send - 待發送數據長度
		/// @return: int
		/// 		-1 - 失敗。初始化socket版本錯誤
		///			0 - 成功
		///			1 - 失敗, 參數【psend】為空或 【len_max_send】等於0 或則len_max_send大於發送緩沖區長度(10k)
		///			2 - 失敗,套接字創建失敗
		///			3 - 失敗, 發送數據失敗, 請調用error_id_()
		/// ------------------------------------------------------------
		virtual int send_(const unsigned char* psend, const unsigned int send_len) = 0;
		
		///  --------------------------------------------------------------------------------
		///  @brief: 	關閉
		///  @return:	int	
		/// 			0 - 成功
		///				其他, 失敗
		///  --------------------------------------------------------------------------------
		virtual int shutdown_() = 0;

		/// ------------------------------------------------------------
		/// @brief:返回錯誤ID
		/// @return: int
		/// 			
		/// ------------------------------------------------------------
		virtual int error_id_() = 0;

	};

創建和銷毀

創建

  • 調用 iudp.h 中的 udp_create_() 可創建iudp。
  • 函數說明
	///  --------------------------------------------------------------------------------
	///  @brief: 	創建 udp對象
	///  @return:	lib_udp		*	
	/// 			NULL- 創建失敗
	///				!= null -  成功
	///  --------------------------------------------------------------------------------
	lib_udp_api iudp		* udp_create_();

銷毀

  • 調用 iudp.h 中的udp_release_(iudp* pudp) 可銷毀udp_create_創建的對象
  • 函數說明
	///  --------------------------------------------------------------------------------
	///  @brief: 	釋放申請的資源, 內部釋放后,見其設置為NULL
	///  @param:	iudp * pudp - 來自【udp_create_】的創建結果
	///  @return:	lib_udp_api lib_udp *	
	/// 			pudp = NULL   
	///  --------------------------------------------------------------------------------
	lib_udp_api iudp * udp_release_(iudp* pudp);
  • 調用范例
pudp_ = udp_release_(pudp_);

項目地址

giteegithub

接口使用范例

  • 你可以在 example/main.cc中找到下面的代碼

代碼

接收

/// to recv data, you must inherit udpsocket_recv class
class my_udp : public irecv_data
{
public:

	/// constructor
	my_udp()
	{
		if (NULL == pudp_)
			pudp_ = udp_create_();//// std::unique_ptr<iudp>(lib_udp::udp_create_()).get();
	}


	/// deconstructor
	virtual ~my_udp()
	{
		pudp_ = udp_release_(pudp_);
	}


	/// you must override this function to recv data
	void on_recv_data_(const unsigned char *pdata_recv, const unsigned int recv_data_len)
	{
		/// -------------------------------------------------------------------------------
		/// 1. recv data
		std::cout << "\n --------------AAAAAA data length = " << recv_data_len << "\n";
		for (unsigned int i = 0; i < recv_data_len; i++)
		{
			if (i == 10)
				std:: cout << "\n";

			std::cout << pdata_recv[i] << ", ";
		}
		
		std::cout << "\n";
	}

	/// -------------------------------------------------------------------------------
	int init_(udp_param& param)
	{
		if (pudp_)
			return pudp_->init_(param, this);

		return -20000;
	}

	/// 
	int send_(const char *psend, const int len_send)
	{
		if (pudp_)
			return pudp_->send_((const unsigned char*)psend, len_send);

		return -20000;
	}

	/// 
	int shutdown_()
	{
		if (pudp_)
			return pudp_->shutdown_();

		return -20000;
	}

	int error_id_()
	{
		if (pudp_)
			return pudp_->error_id_();

		return -20000;
	}

private:
	iudp* pudp_ = NULL;
};

初始化、發送、關閉

	/// -------------------------------------------------------------------------------
	/// 1. to prepare params to initialize
	udp_param param;

	param._is_log_debug		= false;
	param._cast_type 		= lib_udp::udp_multi_cast;
	param._port_dst 		= 10086;
	param._recv_loop 		= true;
	param.socket_version_	= kipv6;

#ifdef _WIN32
	char arr_ipv4[] = "10.0.0.5";
#elif __linux__
	char arr_ipv4[] = "192.168.15.129";
#else 
	char arr_ipv4[] = "10.1.1.3";
#endif///

	std::cout << "local IP = " << arr_ipv4 << std::endl;
	char arr_dst[] = "233.0.0.11";

	//param.dest_ip_.value_ = std::string(arr_dst);
	//param.local_ip_.value_ = std::string(arr_ipv4);

	std::string str_ipv6;
	int indexxxx = 0;
	for (auto list_item : ip6_list)
	{
		str_ipv6 = list_item;
		if (3 == indexxxx)
			break;
		++indexxxx;
	}

	param.dest_ip_.value_	= std::string("FF02::1");
	param.local_ip_.value_ = str_ipv6;/// ip6_list.front();


	
	
	/// -------------------------------------------------------------------------------
	/// 1. to create 
	std::unique_ptr<my_udp> pmy_udp(new(std::nothrow) my_udp);

	//my_udp* pmy_udp = new(std::nothrow) my_udp;

	/// failure
	if (!pmy_udp)
	{
		std::cout << "\n my_udp crated failure\n";

#ifdef _WIN32
		system("pause");
#endif ///_WIN32
		return 0;
	}
	

	/// -------------------------------------------------------------------------------
	/// 2. to initialize udp
	int ret = 0;
	ret = pmy_udp->init_(param);
	if (0 != ret)
	{
		std::cout << "\ninit error , id = " << ret << ", error id=" << pmy_udp->error_id_() << "\n\n";
		ret = pmy_udp->shutdown_();
		if (0 != ret)
				std::cout << "\nshutdown error , id = " << ret << "\n";
#ifdef _WIN32
		system("pause");
#endif ///_WIN32

		return 0;
	}

	//pmy_udp->shutdown_();

	////delete pmy_udp;
	////pmy_udp = NULL;

	//return 0;


	std::cout << "\n init_ip4 success\n";

	/// -------------------------------------------------------------------------------
	/// 4. to send data
	char arr[] = "1234567890";
	for (int i = 0; i < 1; i++)
	{
		int send_len = pmy_udp->send_(arr, strlen(arr));
		/// to output the result 
		std::cout << "udp send, send length = " << send_len << "\n";
		std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 1));
	}



	/// to recv data, it needs to rest
	std::cout << "\n---------------------------main 1111----------------------------\n";
	std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 1));
	std::cout << "\n---------------------------main 2222----------------------------\n";
	pmy_udp->shutdown_();
	std::cout << "\n---------------------------main 3333----------------------------\n";
	std::cout << "\nudp has closed\n";


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM