1. 程式人生 > >C++開發的UDP網路通訊工具類(相容window和linux)

C++開發的UDP網路通訊工具類(相容window和linux)

前段時間做專案用到了網路通訊,自己造了UDP通訊的輪子,能同時在window和linux下執行,並且封裝成類,方便以後使用,考慮到自己也一直在網際網路上獲取資源,現在也把我做的輪子也分享給大家,歡迎參考~

完整程式碼附在下面,如果大家不想複製,可直接從這下載:https://download.csdn.net/download/qq_18108083/10798492

(1)XUdp.h

#ifndef XUDP_H
#define XUDP_H

#ifdef WIN32
#include <windows.h>
#define socklen_t int
#else
#include <arpa/inet.h>
#define closesocket close    //替換close函式
#include <unistd.h>
#endif

class XUdp
{
public:
	int CreateSocket();						 //建立套接字
	void Close();						     //關閉連線
	bool Bind();							 //繫結並監聽埠號
	int Send(const char *buf, int size, char *ip, unsigned short port);	 //傳送資料
	int Recv(char *buf, int bufsize, sockaddr_in *from);				//接收資料

	int SetRecvTimeout(int sec);			 //設定udp接收超時
	int SetSendTimeout(int sec);		     //設定udp傳送超時

	XUdp(unsigned short port = 9000);
	virtual ~XUdp();

private:
	int usock = 0;  //udp服務端的socket create成員函式自己生成
	unsigned short uport = 0;   //建構函式從外獲取

};
#endif

(2)XUdp.cpp

#include "XUdp.h"
#include <iostream>	//IO流操作
#include <string>   //string標準庫
#ifdef WIN32
#include <windows.h>
#define socklen_t int

#else
#include <arpa/inet.h>
#define closesocket close    //替換close函式
#include <unistd.h>
#include <pthread.h>
#endif

XUdp::XUdp(unsigned short port)
{
	//初始化動態連結庫
	//引用lib庫
#ifdef WIN32  //linux下不用初始化網路庫
	static bool first = true;
	if (first)
	{
		first = false;						 //只在首次進入時初始化網路庫
		WSADATA ws;					         //載入Socket庫   專案屬性-連結器-輸入加上 ws2_32.lib
		WSAStartup(MAKEWORD(2, 2), &ws);     //動態庫引用加1    
	}
#endif
	uport = port;
}

XUdp::~XUdp()
{
	delete this;
}

int XUdp::CreateSocket()						 //建立套接字
{
	usock = socket(AF_INET, SOCK_DGRAM, 0);   //TCP/IP  UDP  建立udp 套接字
	if (usock == -1)
	{
		printf("create udp socket failed.\n");
		return -1;
	}
	printf("create udp socket success.\n");
	return 0;
}

void XUdp::Close()					  //關閉連線
{
	if (usock <= 0) return;  //socket出錯
	closesocket(usock);		//已巨集定義

	usock = 0;
	uport = 0;
}

bool XUdp::Bind()			 //繫結並監聽埠號
{
	sockaddr_in saddr;              //資料結構
	saddr.sin_family = AF_INET;     //協議
	saddr.sin_port = htons(uport);   //埠,主機位元組序(小端方式)轉換成網路位元組序(大端方式)
									 //  saddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);                  
	saddr.sin_addr.s_addr = htonl(INADDR_ANY);   //繫結IP到廣播地址INADDR_ANY 0.0.0.0  為了相容linux   

	if (bind(usock, (sockaddr*)&saddr, sizeof(saddr)) != 0)   //安裝sockaddr_in資料結構繫結套接字
	{
		printf("udp bind port %d failed.\n", uport);
		return false;
	}
	printf("udp bind port %d success.\n", uport);
	return true;
}

int XUdp::Send(const char *buf, int size, char *ip, unsigned short port)	 //傳送資料(強制全部發送)
{
	int sendedSize = 0;   //已傳送成功的長度
	sockaddr_in saddr;
	saddr.sin_family = AF_INET;  //tcp/ip協議
	saddr.sin_port = htons(port);//服務端的埠  主機位元組序轉換成網路位元組序
	saddr.sin_addr.s_addr = inet_addr(ip);  //本機的ip地址  字串ip地址轉成整型
	while (sendedSize != size)   //若沒傳送完成,則從斷點開始繼續傳送 直到完成
	{
		int len = sendto(usock, buf + sendedSize, size - sendedSize, 0, (sockaddr*)&saddr, sizeof(saddr));
		if (len <= 0)break;
		sendedSize += len;
	}
	return sendedSize;
}


int XUdp::Recv(char *buf, int bufsize, sockaddr_in *from)	 //接收資料
{
	socklen_t len = sizeof(sockaddr_in);
	int re = recvfrom(usock, buf, bufsize, 0, (sockaddr*)from, &len);   //返回接收的客戶端的網路地址,存在在地址中
	return re;
}

int XUdp::SetRecvTimeout(int sec = 1)   //設定udp接收超時
{
#ifdef WIN32
	int udp_rev_time = sec * 1000;
	if (setsockopt(usock, SOL_SOCKET, SO_RCVTIMEO, (char *)&udp_rev_time, sizeof(int))<0)
	{
		printf("set udp receive failed.\n");
		return -1;
	}
	printf("set udp recv timeout success. %d seconds\n", sec);
	return 0;
#else
	struct timeval udp_rev_time;
	udp_rev_time.tv_sec = sec;
	udp_rev_time.tv_usec = 0;
	if (setsockopt(usock, SOL_SOCKET, SO_RCVTIMEO, (char *)&udp_rev_time, sizeof(udp_rev_time))<0)
	{
		printf("set udp receive failed.\n");
		return -1;
	}
	printf("set udp recv timeout success. %d seconds\n", sec);
	return 0;
#endif
}


int XUdp::SetSendTimeout(int sec = 1)   //設定udp傳送超時
{
#ifdef WIN32
	int udp_rev_time = sec;
	if (setsockopt(usock, SOL_SOCKET, SO_SNDTIMEO, (char *)&udp_rev_time, sizeof(int))<0)
	{
		printf("set udp send failed.");
		return -1;
	}
	return 0;
	printf("set udp send timeout success. %d seconds\n", sec);
#else
	struct timeval udp_rev_time;
	udp_rev_time.tv_sec = sec;
	udp_rev_time.tv_usec = 0;
	if (setsockopt(usock, SOL_SOCKET, SO_SNDTIMEO, (char *)&udp_rev_time, sizeof(udp_rev_time))<0)
	{
		printf("set udp send failed.");
		return -1;
	}
	printf("set udp send timeout success. %d seconds\n", sec);
	return 0;
#endif
}