一、一度書けばいいものがある--UDPネットワーク通信類テンプレート


UDP(User Data Protocol、ユーザー・データ・レポート・プロトコル)1、UDPは非接続のプロトコルであり、データを転送する前にソースと端末は接続を確立せず、転送したい場合はアプリケーションからのデータを簡単にキャプチャし、できるだけ早くネットワークに投げつける.送信側では、UDPがデータを送信する速度は、アプリケーションがデータを生成する速度、コンピュータの能力、および伝送帯域幅によってのみ制限される.受信側では、UDPは各メッセージセグメントをキューに配置し、アプリケーションはキューからメッセージセグメントを1つずつ読み出す.
2、伝送データは接続を確立しないので、送受信状態などを含めて接続状態を維持する必要もないので、1台のサービス機は同時に複数のクライアントに同じメッセージを伝送することができる.
3、UDPパケットのタイトルは短く、8バイトしかなく、TCPの20バイトパケットに対する追加コストは小さい.
4、スループットは混雑制御アルゴリズムによって調節されず、アプリケーションソフトウェアがデータを生成する速度、伝送帯域幅、ソース端と端末ホストの性能によって制限される.
5、UDPは最大限の努力を尽くして交付することを使用して、つまり信頼性の交付を保証しないので、ホストは複雑なリンク状態表を維持する必要はありません(この中には多くのパラメータがあります).
6、UDPはメッセージ向けです.送信側のUDPは,アプリケーションに対して渡されたメッセージを,ヘッダを追加するとIP層に下向きに渡す.分割もマージもせず、これらのメッセージの境界を保持するため、アプリケーションは適切なメッセージサイズを選択する必要があります.
私達はいつも“ping”の命令を使って2台のホストの間TCP/IP通信が正常かどうかをテストして、実は“ping”の命令の原理は相手のホストにUDPのパケットを送信して、それから相手のホストはパケットを受け取ったことを確認して、もしパケットが到着したメッセージが直ちにフィードバックして帰ってくるならば、それではネットワークは通じています.
pingコマンドは、ホストとホストの間で通信可能かどうかを検出するために使用されます.あるホストにpingできない場合は、このホストと接続できないことを示します.pingコマンドは、IPおよびネットワーク制御情報プロトコル(ICMP)を使用するため、UDP/TCPおよびアプリケーションには関与しない.目的のホストにicmp返信要求メッセージを送信します.
ICMPプロトコルは、宛先ホストがICMP返信メッセージをソースホストに返す必要があることを規定している.ソースホストが一定時間以内に応答を受信した場合、ホストは到達可能であると考えられます.
UDPのヘッダ構造:ソースポート16ビット
宛先ポート16ビット
長さ16ビット
チェックサム16ビット1、1回で十分なものがあります–UDPネットワーク通信クラステンプレート
次は简単なUDP通信のクラステンプレートを书いて、无限に多重化することができて、いくつかのものは1回书くだけで十分です~
まずはUDP受信
#ifndef UDPRECVCONFIG_H
#define UDPRECVCONFIG_H

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "sys/types.h"
#include "errno.h"
#include "assert.h"

template <typename NetRecvDataType> class UdpNetRecvCtrl
{
     
public:
	//       
	UdpNetRecvCtrl(char *LocalIp, unsigned int iRecvPort, bool bGroup = false, char * sGroupIp = "", unsigned int iMsg = 0)
	{
     
		assert((iRecvPort > 1024) && (iRecvPort < 65535));

		m_strLocalIP = LocalIp;
		m_iLocalPort = iRecvPort;
		m_bGroupRecv = bGroup;
		m_strGroupIP = sGroupIp;
		
		m_bSockValid = false;
		m_bRecvValid = false;
		m_iRecvCount = 0;
		m_iRecvLen   = 0;
		m_Socket     = 0;
		strSockName  = "";
		m_iMsg       = iMsg;

		bSockNameValid = false;

		m_Socket = socket(AF_INET, SOCK_DGRAM, 0);
		if(m_Socket == -1)
		{
     
			perror("Socket Create Fail");
			return;
		}
		//    
		memset(&m_addr, 0, sizeof(m_addr));
		m_addr.sin_family = AF_INET;
		m_addr.sin_port = htons(m_iLocalPort);
		m_addr.sin_addr.s_addr = inet_addr(m_strLocalIP);
		reuse = true;
		ret = setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(bool));
		if(ret < 0)
		{
     
			perror("Set Socketopt Fail");
			return;
		}

		ret = bind(m_Socket, (struct sockaddr *)&m_addr, sizeof(m_addr));
		if(ret < 0)
		{
     
			perror("bind error");
			return;
		}

		if(m_bGroupRecv)
		{
     
			//    
			struct ip_mreq mreq;
			memset(&mreq, 0, sizeof(mreq));
			mreq.imr_interface.s_addr = inet_addr(m_strGroupIP);
			mreq.imr_multiaddr.s_addr = inet_addr(m_strGroupIP);

			ret = setsockopt(m_Socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
			if(ret < 0)
			{
     
				perror("set multiaddr fail");
				return;
			}
			
			//    
			bool bLOOP = false;
			ret = setsockopt(m_Socket, SOL_SOCKET, IP_MULTICAST_LOOP, (char *)&bLOOP, sizeof(bool));
			if(ret < 0)
			{
     
				perror("set no loop fail");
				return;
			}
		}

		m_bSockValid = true;
	}
	//    
	~UdpNetRecvCtrl(void)
	{
     
		if(m_Socket)
		{
     
			close(m_Socket);
			sleep(5);//     delete   
		}
	}

public:
	//      
	int recv(NetRecvDataType &data)
	{
     
		if(m_bSockValid == false)
		{
     
			m_bRecvValid = false;
			return -1;
		}
		m_iRecvLen = -1;

		ret = recvfrom(m_Socket, (char *)(&recvBuf), sizeof(recvBuf), 0, (struct sockaddr *)&m_AddrDataSource, &m_iLenAddrDataSource);
		if(ret > 0)
		{
     
			m_iRecvLen = ret;
			memcpy((char *)(&data), recvBuf, sizeof(data));
			m_iRecvCount += 1;
			m_bRecvValid = true;
		}
		else
		{
     
			m_bRecvValid = false;
			return m_iRecvLen;
		}

	}
	//      
	unsigned int getRecvCount()
	{
     
		return m_iRecvCount;
	}
	//      
	int getRecvLen()
	{
     
		return m_iRecvLen;
	}
	//    
	int getRecvMsg()
	{
     
		return m_iMsg;
	}
private:
	//     
	char * 		   		m_strLocalIP;		//  IP
	unsigned int   		m_iLocalPort;		//    
	int 		   		ret;				    //    
	bool 		   		reuse;		
	bool 		   		m_bGroupRecv;		//    
	char *		   		m_strGroupIP;		//  IP

	int 		   		m_Socket;			
	struct sockaddr_in  m_addr;			
	char 		   		recvBuf[1024];		//    

	struct sockaddr_in m_AddrDataSource;		//      
	socklen_t   	   m_iLenAddrDataSource;

	bool 		   		m_bSockValid;		//      
	bool 		   		m_bRecvValid;		//    
	unsigned int   		m_iRecvCount;		//    
	int 		   		m_iRecvLen;			//    

	bool 		   		bSockNameValid;
	char *		   		strSockName;

	bool 		   		m_bAsynchValid;
	unsigned int   		m_iMsg;

};



#endif


次はUDP送信
#ifndef UDPSENDCONFIG_H
#define UDPSENDCONFIG_H

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "sys/types.h"
#include "errno.h"
#include "assert.h"

template <typename NetSendDataType> class UdpNetSendCtrl
{
     
public:
	//       
	UdpNetSendCtrl(char *LocalIp, unsigned int iLocalPort, char *sSendIP, unsigned int SendPort)
	{
     
		m_strLocalIP = LocalIp;
		m_iLocalPort = iLocalPort;
		m_strSendPort= SendPort;
		m_strSendIP  = sSendIP;

		m_bSockValid = false;
		m_bSendValid = false;
		m_iSendCount = 0;
		m_iSendLen   = 0;
		m_Socket     = 0;

		m_Socket = socket(AF_INET, SOCK_DGRAM, 0);
		if(m_Socket == -1)
		{
     
			perror("Socket Create Fail");
			return;
		}
		//    
		memset(&m_addr, 0, sizeof(m_addr));
		m_addr.sin_family = AF_INET;
		m_addr.sin_port = htons(m_iLocalPort);
		m_addr.sin_addr.s_addr = inet_addr(m_strLocalIP);
		//    
		memset(&m_addrDst, 0, sizeof(m_addrDst));
		m_addrDst.sin_family = AF_INET;
		m_addrDst.sin_port = htons(m_strSendPort);
		m_addrDst.sin_addr.s_addr = inet_addr(m_strSendIP);
		m_iLenAddrDst = sizeof(m_addrDst);
		reuse = true;
		ret = setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(int));
		if(ret < 0)
		{
     
			perror("Set Socketopt Fail");
			return;
		}
		ret = bind(m_Socket, (struct sockaddr *)&m_addr, sizeof(m_addr));
		if(ret < 0)
		{
     
			perror("bind error");
			return;
		}

		m_bSockValid = true;
	}
	//    
	~UdpNetSendCtrl(void)
	{
     
		if(m_Socket)
		{
     
			close(m_Socket);
			sleep(5);//     delete   
		}
	}

public:
	//      
	int send(NetSendDataType &data)
	{
     
		if(m_bSockValid == false)
		{
     
			m_bSendValid = false;
			return -1;
		}
		m_iSendLen = -1;

		ret = sendto(m_Socket, (char *)(&data), sizeof(data), 0, (struct sockaddr *)&m_addrDst, m_iLenAddrDst);
		if(ret > 0)
		{
     
			m_iSendLen = ret;
			m_iSendCount += 1;
			m_bSendValid = true;
		}
		else
		{
     
			m_bSendValid = false;
			return m_iSendLen;
		}

	}
	//      
	unsigned int getSendCount()
	{
     
		return m_iSendCount;
	}
	//      
	int getSendLen()
	{
     
		return m_iSendLen;
	}
private:
	//     
	char * 		   	   m_strLocalIP;		//  IP
	unsigned int 	   m_iLocalPort;		//    
	int 		   	   ret;					//     
	bool 		   	   reuse;	
	unsigned int	   m_strSendPort;		//    		
	char *		   	   m_strSendIP;			//  IP

	int 		   	   m_Socket;			//   
	struct sockaddr_in m_addr;
	char * 		   	   SendBuf;
	struct sockaddr_in m_addrDst;
	socklen_t   	   m_iLenAddrDst;

	bool 		   	   m_bSockValid;
	bool 		   	   m_bSendValid;
	unsigned int 	   m_iSendCount;
	int 		   	   m_iSendLen;
};



#endif


呼び出しセクション
#include "UdpRecvConfig.h"
#include "UdpSendConfig.h"
#include "iostream"
#include "pthread.h"
#include "unistd.h"
using namespace std;

typedef struct _Data{
     
	unsigned short number;
	unsigned short length;
	unsigned short value;
}M_DATA, *PM_DATA;


void *my_thread_1(void * arg)
{
     
	UdpNetRecvCtrl<M_DATA> *temp = (UdpNetRecvCtrl<M_DATA> *)arg;
	M_DATA data;

	while(1)
	{
     
		temp->recv(data);
		printf("recv:%d,%d,%d",data.number, data.length, data.value);
	}
	return NULL;
}

void *my_thread_2(void * arg)
{
     	
	UdpNetSendCtrl<M_DATA> *temp = (UdpNetSendCtrl<M_DATA> *)arg;
	M_DATA my_data;
	my_data.number = 1;
	my_data.length = 6;
	my_data.value  = 3;
	while(1)
	{
     
		temp->send(my_data);
		my_data.number++;
		sleep(1);
	}
	return NULL;
}

int main()
{
     
	pthread_t _id0, _id1;
	M_DATA m_data;
	UdpNetRecvCtrl<M_DATA> *m_udp_recv;
	UdpNetSendCtrl<M_DATA> *m_udp_send;
	char *ip = new char[100];
	ip = "127.0.0.1";
	m_udp_send = new UdpNetSendCtrl<M_DATA>(ip, 8226, "127.0.0.1", 8225);
	m_udp_recv = new UdpNetRecvCtrl<M_DATA>(ip, 8225, false, "", 0);
	pthread_create(&_id0, NULL, my_thread_1, m_udp_recv);
	pthread_create(&_id1, NULL, my_thread_2, m_udp_send);
	
	pthread_join(_id0, NULL);
	pthread_join(_id1, NULL);
	return 0;
}


byジョジョリン