RakNet网络框架简单入门

1,715 阅读22分钟

        raknet是采用c++语言编写的一套基于UDP协议的高性能网络框架,主要使用在游戏中,当然了,其他项目也可以使用。还有,他是跨平台的。

        由于目前的手游项目的网络框架使用的就是它,花了点时间看了看,这里写个比较简单的例子来说明该如何使用它。要是在项目中使用,只需要扩展这个代码即可。

        raknet官网上下载资料包,使用vs2008及以上的版本打开里面的项目工程,编译里面的DLL项目,生成RakNet_DLL_Debug_Win32.lib和RakNet_DLL_Debug_Win32.dll文件,当然这是Debug模式下。

        

        现在我们实现这样一个效果,server接受client发送过来的数据,并添加一些字符串否再发给client,client显示发送和接受的数据。发送的内容使用一个结构体来存放。

我们新建一个文件夹,将刚刚生成的lib文件拷贝进去,并且将解压出来的source文件夹一起复制过去,里面含有raknet的头文件。

在vs中创建win32控制台程序工程,放到新建的文件夹中,工程属性中配置属性C/C++常规附加库包含目录中添加source文件夹,连接器输入中添加RakNet_DLL_Debug_Win32.lib,连接器常规附加库目录协商lib文件所在的目录。

首先看看server端代码:NetMgr.h

  1. #ifndef __NETMGR_H__  
  2. #define __NETMGR_H__  
  3.   
  4. class NetMgr  
  5. {  
  6. public:  
  7.     NetMgr();  
  8.     ~NetMgr();  
  9.   
  10.     //初始化网络  
  11.     void init_net_work() const;  
  12.   
  13.     //接收网络消息  
  14.     void net_work_update() const;  
  15.   
  16.     //发送数据给client  
  17.     void send_data_to_client() const;  
  18.   
  19.     //接收client的数据  
  20.     void receive_data_from_client(const unsigned char *msg_data)  const;  
  21.   
  22. private:  
  23.     //处理server发送过来的消息  
  24.     void _process_client_message() const;  
  25.   
  26. public:  
  27.     unsigned short server_port;  
  28.     int max_client;  
  29. };  
  30.   
  31. #endif  
#ifndef __NETMGR_H__
#define __NETMGR_H__

class NetMgr
{
public:
	NetMgr();
	~NetMgr();

	//初始化网络
	void init_net_work() const;

	//接收网络消息
	void net_work_update() const;

	//发送数据给client
	void send_data_to_client() const;

	//接收client的数据
	void receive_data_from_client(const unsigned char *msg_data) const;

private:
	//处理server发送过来的消息
	void _process_client_message() const;

public:
	unsigned short server_port;
	int max_client;
};

#endif


再看看NetMgr.cpp:
  1. #include "NetMgr.h"  
  2. #include "../../Source/RakPeerInterface.h"  
  3. #include "../../Source/RakNetTypes.h"  
  4. #include "../../Source/MessageIdentifiers.h"  
  5. #include "../../Source/BitStream.h"  
  6.   
  7. #include <iostream>  
  8. #include "ServerClientMessage.h"  
  9. #include "ServerClientStruct.h"  
  10.   
  11.   
  12. RakNet::RakPeerInterface *net_peer;         //网络消息  
  13. RakNet::Packet *net_packet;                 //网络消息包  
  14.   
  15.   
  16. NetMgr::NetMgr()  
  17.     : server_port(10001)  
  18.     , max_client(1000)  
  19. {  
  20.   
  21. }  
  22.   
  23. NetMgr::~NetMgr()  
  24. {  
  25.   
  26. }  
  27.   
  28. //初始化网络  
  29. void NetMgr::init_net_work() const  
  30. {  
  31.     //初始化网络消息  
  32.     net_peer = RakNet::RakPeerInterface::GetInstance();  
  33.     if (NULL == net_peer)  
  34.     {  
  35.         std::cout << "GetInstance failed" << std::endl;  
  36.         return;  
  37.     }  
  38.   
  39.     std::cout << "Start Game Server ......" << server_port << std::endl;  
  40.   
  41.     //开启网络线程来监听相应的端口  
  42.     //Startup函数的第一个参数是接受的最大连接数,客户端一般设置成1  
  43.     //第二个参数就是要监听的端口。SocketDescriptor监听制定的端口,他是一种套接字,服务器一般设置成SocketDescriptor(server_port, 0)  
  44.     //第三个参数是SocketDescriptor数组的大小,传1表明不确定。  
  45.     int start_up = net_peer->Startup(1, &RakNet::SocketDescriptor(server_port, 0), 1);  
  46.     if (start_up > 0)  
  47.     {  
  48.         std::cout << "Startup failed" << std::endl;  
  49.         return;  
  50.     }  
  51.   
  52.     //SetMaximumIncomingConnections容许最多的连接数量  
  53.     net_peer->SetMaximumIncomingConnections(max_client);  
  54. }  
  55.   
  56. //接收网络消息  
  57. void NetMgr::net_work_update() const  
  58. {  
  59.     //Receive从消息队列中获取消息  
  60.     for (net_packet = net_peer->Receive(); net_packet; net_peer->DeallocatePacket(net_packet), net_packet = net_peer->Receive())  
  61.     {  
  62.         switch (net_packet->data[0])  
  63.         {  
  64.         case ID_REMOTE_DISCONNECTION_NOTIFICATION:  
  65.             std::cout << "Another client has disconnected" << std::endl;  
  66.             break;  
  67.         case ID_REMOTE_CONNECTION_LOST:  
  68.             std::cout << "Another client has lost the connection" << std::endl;  
  69.             break;  
  70.         case ID_REMOTE_NEW_INCOMING_CONNECTION:  
  71.             std::cout << "Another client has connected" << std::endl;  
  72.             break;  
  73.         case ID_CONNECTION_REQUEST_ACCEPTED:  
  74.             std::cout << "Our connection request has been accepted for server" << std::endl;  
  75.             break;  
  76.         case ID_NEW_INCOMING_CONNECTION:  
  77.             std::cout << "A connection is incoming  " << std::endl;  
  78.             break;  
  79.         case ID_NO_FREE_INCOMING_CONNECTIONS:  
  80.             std::cout << "The server is full" << std::endl;  
  81.             break;  
  82.         case ID_DISCONNECTION_NOTIFICATION:  
  83.             std::cout << "A client has disconnected" << std::endl;  
  84.             break;  
  85.         case ID_CONNECTION_LOST:  
  86.             std::cout << "A client lost the connection  " << std::endl;  
  87.             break;  
  88.         case ID_USER_PACKET_ENUM:  
  89.             _process_client_message();              //用户自定义消息入口  
  90.             break;  
  91.         default:  
  92.             std::cout << "Message with identifier %d has arrived" << net_packet->data[0] << std::endl;  
  93.             break;  
  94.         }  
  95.     }  
  96. }  
  97.   
  98. // client 发送过来的消息  
  99. void NetMgr::_process_client_message() const  
  100. {  
  101.     int message_id = 0;  
  102.     //将消息解析出来,使用BitStream  
  103.     //IgnoreBytes忽略掉最外层的raknet的消息类型  
  104.     RakNet::BitStream bs_in(net_packet->data, net_packet->length, false);  
  105.     bs_in.IgnoreBytes(sizeof(RakNet::MessageID));  
  106.     bs_in.Read(message_id);  
  107.   
  108.     //偏移掉自定义的消息,获取实际数据,raknet的消息类型大小是一个字节,自定义的结构体是4个字节(32位机器)  
  109.     unsigned char *msg_data = net_packet->data;  
  110.     msg_data += sizeof(unsigned long) + sizeof(unsigned  char);  
  111.   
  112.     switch (message_id)  
  113.     {  
  114.     case msg_connect_server:  
  115.         this->receive_data_from_client(msg_data);  
  116.         break;  
  117.   
  118.     default:  
  119.         break;  
  120.     }  
  121. }  
  122.   
  123. // 接收 client 数据 并回应client  
  124. void NetMgr::receive_data_from_client(const unsigned char *msg_data)  const  
  125. {  
  126.     connect_server *receive_data = (connect_server *)msg_data;  
  127.   
  128.     std::cout << "receive from client data is :" << receive_data->content << std::endl;  
  129.   
  130.     connect_server_return send_data;  
  131.     memset(&send_data, 0, sizeof(connect_server_return));  
  132.   
  133.     std::string content = receive_data->content;  
  134.     content += ". server already receive client data, this is server data";  
  135.   
  136.     sprintf_s(send_data.content_return, "%s", content.c_str());  
  137.   
  138.     std::cout << "server data is :" << send_data.content_return << std::endl;  
  139.   
  140.     //使用BitStream 对象来封装数据  
  141.     RakNet::BitStream stream;  
  142.     //先写入raknet的消息类型(raknet中自定义类型(ID_USER_PACKET_ENUM))  
  143.     stream.Write(( RakNet::MessageID )ID_USER_PACKET_ENUM);  
  144.     //再写入我们自己定义的消息类型  
  145.     stream.Write(msg_connect_server_return);  
  146.     //将数据写到stream中,第一个参数是要写入的数据字节数组,第二个是数据的位数  
  147.     stream.WriteBits((unsigned char *)&send_data , sizeof(connect_server_return) * 8);  
  148.     //将数据发送到指定的地方  
  149.     //第一个参数是要发送的bitstream对象  
  150.     //第二个参数是发送的优先级  
  151.     //第三个参数是发送的可靠性,这里使用RELIABLE_ORDERED,具体在PacketPriority.h枚举的PacketReliability中有具体说明  
  152.     //自己看api,这里设置成0  
  153.     //接收方地址  
  154.     //是否广播,注意下,要是用那个true,上一个参数就是不需要接受数据的地址  
  155.     net_peer->Send(&stream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, net_packet->systemAddress, false);  
  156. }  
#include "NetMgr.h"
#include "../../Source/RakPeerInterface.h"
#include "../../Source/RakNetTypes.h"
#include "../../Source/MessageIdentifiers.h"
#include "../../Source/BitStream.h"

#include <iostream>
#include "ServerClientMessage.h"
#include "ServerClientStruct.h"


RakNet::RakPeerInterface *net_peer;			//网络消息
RakNet::Packet *net_packet;					//网络消息包


NetMgr::NetMgr()
	: server_port(10001)
	, max_client(1000)
{

}

NetMgr::~NetMgr()
{

}

//初始化网络
void NetMgr::init_net_work() const
{
	//初始化网络消息
	net_peer = RakNet::RakPeerInterface::GetInstance();
	if (NULL == net_peer)
	{
		std::cout << "GetInstance failed" << std::endl;
		return;
	}

	std::cout << "Start Game Server ......" << server_port << std::endl;

	//开启网络线程来监听相应的端口
	//Startup函数的第一个参数是接受的最大连接数,客户端一般设置成1
	//第二个参数就是要监听的端口。SocketDescriptor监听制定的端口,他是一种套接字,服务器一般设置成SocketDescriptor(server_port, 0)
	//第三个参数是SocketDescriptor数组的大小,传1表明不确定。
	int start_up = net_peer->Startup(1, &RakNet::SocketDescriptor(server_port, 0), 1);
	if (start_up > 0)
	{
		std::cout << "Startup failed" << std::endl;
		return;
	}

	//SetMaximumIncomingConnections容许最多的连接数量
	net_peer->SetMaximumIncomingConnections(max_client);
}

//接收网络消息
void NetMgr::net_work_update() const
{
	//Receive从消息队列中获取消息
	for (net_packet = net_peer->Receive(); net_packet; net_peer->DeallocatePacket(net_packet), net_packet = net_peer->Receive())
	{
		switch (net_packet->data[0])
		{
		case ID_REMOTE_DISCONNECTION_NOTIFICATION:
			std::cout << "Another client has disconnected" << std::endl;
			break;
		case ID_REMOTE_CONNECTION_LOST:
			std::cout << "Another client has lost the connection" << std::endl;
			break;
		case ID_REMOTE_NEW_INCOMING_CONNECTION:
			std::cout << "Another client has connected" << std::endl;
			break;
		case ID_CONNECTION_REQUEST_ACCEPTED:
			std::cout << "Our connection request has been accepted for server" << std::endl;
			break;
		case ID_NEW_INCOMING_CONNECTION:
			std::cout << "A connection is incoming  " << std::endl;
			break;
		case ID_NO_FREE_INCOMING_CONNECTIONS:
			std::cout << "The server is full" << std::endl;
			break;
		case ID_DISCONNECTION_NOTIFICATION:
			std::cout << "A client has disconnected" << std::endl;
			break;
		case ID_CONNECTION_LOST:
			std::cout << "A client lost the connection  " << std::endl;
			break;
		case ID_USER_PACKET_ENUM:
			_process_client_message();				//用户自定义消息入口
			break;
		default:
			std::cout << "Message with identifier %d has arrived" << net_packet->data[0] << std::endl;
			break;
		}
	}
}

// client 发送过来的消息
void NetMgr::_process_client_message() const
{
	int message_id = 0;
	//将消息解析出来,使用BitStream
	//IgnoreBytes忽略掉最外层的raknet的消息类型
	RakNet::BitStream bs_in(net_packet->data, net_packet->length, false);
	bs_in.IgnoreBytes(sizeof(RakNet::MessageID));
	bs_in.Read(message_id);

	//偏移掉自定义的消息,获取实际数据,raknet的消息类型大小是一个字节,自定义的结构体是4个字节(32位机器)
	unsigned char *msg_data = net_packet->data;
	msg_data += sizeof(unsigned long) + sizeof(unsigned char);

	switch (message_id)
	{
	case msg_connect_server:
		this->receive_data_from_client(msg_data);
		break;

	default:
		break;
	}
}

// 接收 client 数据 并回应client
void NetMgr::receive_data_from_client(const unsigned char *msg_data) const
{
	connect_server *receive_data = (connect_server *)msg_data;

	std::cout << "receive from client data is :" << receive_data->content << std::endl;

	connect_server_return send_data;
	memset(&send_data, 0, sizeof(connect_server_return));

	std::string content = receive_data->content;
	content += ". server already receive client data, this is server data";

	sprintf_s(send_data.content_return, "%s", content.c_str());

	std::cout << "server data is :" << send_data.content_return << std::endl;

	//使用BitStream 对象来封装数据
	RakNet::BitStream stream;
	//先写入raknet的消息类型(raknet中自定义类型(ID_USER_PACKET_ENUM))
	stream.Write(( RakNet::MessageID )ID_USER_PACKET_ENUM);
	//再写入我们自己定义的消息类型
	stream.Write(msg_connect_server_return);
	//将数据写到stream中,第一个参数是要写入的数据字节数组,第二个是数据的位数
	stream.WriteBits((unsigned char *)&send_data , sizeof(connect_server_return) * 8);
	//将数据发送到指定的地方
	//第一个参数是要发送的bitstream对象
	//第二个参数是发送的优先级
	//第三个参数是发送的可靠性,这里使用RELIABLE_ORDERED,具体在PacketPriority.h枚举的PacketReliability中有具体说明
	//自己看api,这里设置成0
	//接收方地址
	//是否广播,注意下,要是用那个true,上一个参数就是不需要接受数据的地址
	net_peer->Send(&stream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, net_packet->systemAddress, false);
}


最后看看Main.cpp:

  1. #include "NetMgr.h"  
  2. #include <iostream>  
  3.   
  4. int main()  
  5. {  
  6.     NetMgr *p = new NetMgr;  
  7.   
  8.     p->init_net_work();  
  9.   
  10.     while (true)  
  11.     {  
  12.         p->net_work_update();  
  13.     }  
  14.       
  15.     delete p;  
  16.     p = NULL;  
  17.   
  18.     return 0;  
  19. }  
#include "NetMgr.h"
#include <iostream>

int main()
{
	NetMgr *p = new NetMgr;

	p->init_net_work();

	while (true)
	{
		p->net_work_update();
	}
	
	delete p;
	p = NULL;

	return 0;
}


这里server 和client通信传输的数据我们使用结构体来保存,传输的消息类型在枚举变量中列出。下面这两个头文件client和server工程都都需要。 看看消息类型的头文件:ServerClientMessage.h

  1. #ifndef __SERVERCLIENTMESSAGE_H__  
  2. #define __SERVERCLIENTMESSAGE_H__  
  3.   
  4. enum message_type  
  5. {  
  6.     msg_connect_server = 101,  
  7.     msg_connect_server_return,  
  8. };  
  9.   
  10. #endif  
#ifndef __SERVERCLIENTMESSAGE_H__
#define __SERVERCLIENTMESSAGE_H__

enum message_type
{
	msg_connect_server = 101,
	msg_connect_server_return,
};

#endif

保存数据的结构体文件:ServerClientStruct.h
  1. #ifndef __SERVERCLIENTSTRUCT_H__  
  2. #define  __SERVERCLIENTSTRUCT_H__  
  3.   
  4. #pragma once  
  5.   
  6.   
  7. #pragma pack(push, 1)  
  8. struct connect_server  
  9. {  
  10.     char content[500];  
  11. };  
  12. #pragma pack(pop)  
  13.   
  14. #pragma pack(push, 1)  
  15. struct connect_server_return  
  16. {  
  17.     char content_return[1000];  
  18. };  
  19. #pragma pack(pop)  
  20.   
  21.   
  22. #endif  
#ifndef __SERVERCLIENTSTRUCT_H__
#define  __SERVERCLIENTSTRUCT_H__

#pragma once


#pragma pack(push, 1)
struct connect_server
{
	char content[500];
};
#pragma pack(pop)

#pragma pack(push, 1)
struct connect_server_return
{
	char content_return[1000];
};
#pragma pack(pop)


#endif

上面的是server端,来看看client端。

NetMgr.h

  1. #ifndef __NETSERVERMGR_H__  
  2. #define __NETSERVERMGR_H__  
  3.   
  4. #include <string>  
  5.   
  6. class NetServerMgr  
  7. {  
  8. public:  
  9.     NetServerMgr();  
  10.     ~NetServerMgr();  
  11.   
  12.     //初始化网络  
  13.     void init_net_work() const;  
  14.   
  15.     //接收网络消息  
  16.     void net_work_update();  
  17.   
  18.     //发送数据给server  
  19.     void send_data_to_server() const;  
  20.   
  21.     //接收server的数据  
  22.     void receive_data_from_server(const unsigned char *msg_data)  const;  
  23.   
  24. private:  
  25.     //处理server发送过来的消息  
  26.     void _process_server_message() const;  
  27.   
  28. public:  
  29.     std::string server_ip;  
  30.     unsigned short server_port;  
  31. };  
  32.   
  33. #endif  
#ifndef __NETSERVERMGR_H__
#define __NETSERVERMGR_H__

#include <string>

class NetServerMgr
{
public:
	NetServerMgr();
	~NetServerMgr();

	//初始化网络
	void init_net_work() const;

	//接收网络消息
	void net_work_update();

	//发送数据给server
	void send_data_to_server() const;

	//接收server的数据
	void receive_data_from_server(const unsigned char *msg_data) const;

private:
	//处理server发送过来的消息
	void _process_server_message() const;

public:
	std::string server_ip;
	unsigned short server_port;
};

#endif

NetMrg.cpp
  1. #include "NetServerMgr.h"  
  2. #include "../../Source/RakPeerInterface.h"  
  3. #include "../../Source/RakNetTypes.h"  
  4. #include "../../Source/MessageIdentifiers.h"  
  5. #include "../../Source/BitStream.h"  
  6.   
  7. #include <iostream>  
  8. #include "ServerClientMessage.h"  
  9. #include "ServerClientStruct.h"  
  10.   
  11.   
  12. RakNet::RakPeerInterface *net_peer;         //网络消息  
  13. RakNet::Packet *net_packet;                 //网络消息包  
  14. RakNet::SystemAddress server_address;       //server 地址  
  15.   
  16. NetServerMgr::NetServerMgr()  
  17.     : server_ip("localhost")  
  18.     , server_port(10001)  
  19. {  
  20.   
  21. }  
  22.   
  23. NetServerMgr::~NetServerMgr()  
  24. {  
  25.   
  26. }  
  27.   
  28. //初始化网络  
  29. void NetServerMgr::init_net_work() const  
  30. {  
  31.     //初始化网络消息  
  32.     net_peer = RakNet::RakPeerInterface::GetInstance();  
  33.     if (NULL == net_peer)  
  34.     {  
  35.         std::cout << "GetInstance failed" << std::endl;  
  36.         return;  
  37.     }  
  38.   
  39.     int start_up = net_peer->Startup(1, &RakNet::SocketDescriptor(), 1);  
  40.     if (start_up > 0)  
  41.     {  
  42.         std::cout << "Startup failed" << std::endl;  
  43.         return;  
  44.     }  
  45.   
  46.     //Connect 连接server  
  47.     //successful 返回 CONNECTION_ATTEMPT_STARTED  
  48.     bool rs = (net_peer->Connect(server_ip.c_str(), server_port, NULL, 0, 0) == RakNet::CONNECTION_ATTEMPT_STARTED);  
  49.     if (!rs)  
  50.     {  
  51.         std::cout << "connect server failed" << std::endl;  
  52.         return;  
  53.     }  
  54. }  
  55.   
  56. //接收网络消息  
  57. void NetServerMgr::net_work_update()  
  58. {  
  59.     for (net_packet = net_peer->Receive(); net_packet; net_peer->DeallocatePacket(net_packet), net_packet = net_peer->Receive())  
  60.     {  
  61.         switch (net_packet->data[0])  
  62.         {  
  63.         case ID_REMOTE_DISCONNECTION_NOTIFICATION:  
  64.             std::cout << "Another client has disconnected" << std::endl;  
  65.             break;  
  66.         case ID_REMOTE_CONNECTION_LOST:  
  67.             std::cout << "Another client has lost the connection" << std::endl;  
  68.             break;  
  69.         case ID_REMOTE_NEW_INCOMING_CONNECTION:  
  70.             std::cout << "Another client has connected" << std::endl;  
  71.             break;  
  72.         //client连接上server后会触发  
  73.         case ID_CONNECTION_REQUEST_ACCEPTED:  
  74.             std::cout << "Our connection request has been accepted for server" << std::endl;  
  75.             server_address = net_packet->systemAddress;  
  76.             this->send_data_to_server();  
  77.             break;  
  78.         case ID_NEW_INCOMING_CONNECTION:  
  79.             std::cout << "A connection is incoming  " << std::endl;  
  80.             break;  
  81.         case ID_NO_FREE_INCOMING_CONNECTIONS:  
  82.             std::cout << "The server is full" << std::endl;  
  83.             break;  
  84.         case ID_DISCONNECTION_NOTIFICATION:  
  85.             std::cout << "A client has disconnected" << std::endl;  
  86.             break;  
  87.         case ID_CONNECTION_LOST:  
  88.             std::cout << "A client lost the connection  " << std::endl;  
  89.             break;  
  90.         case ID_USER_PACKET_ENUM:  
  91.             _process_server_message();              //用户自定义消息入口  
  92.             break;  
  93.         default:  
  94.             std::cout << "Message with identifier %d has arrived" << net_packet->data[0] << std::endl;  
  95.             break;  
  96.         }  
  97.     }  
  98. }  
  99.   
  100. // server 发送过来的消息  
  101. void NetServerMgr::_process_server_message() const  
  102. {  
  103.     int message_id = 0;  
  104.     RakNet::BitStream bs_in(net_packet->data, net_packet->length, false);  
  105.     bs_in.IgnoreBytes(sizeof(RakNet::MessageID));  
  106.     bs_in.Read(message_id);  
  107.   
  108.     unsigned char *msg_data = net_packet->data;  
  109.     msg_data += sizeof(unsigned long) + sizeof(unsigned  char);  
  110.     switch (message_id)  
  111.     {  
  112.     case msg_connect_server_return:  
  113.         this->receive_data_from_server(msg_data);  
  114.         break;  
  115.   
  116.     default:  
  117.         break;  
  118.     }  
  119. }  
  120.   
  121. // 向 server 发送数据  
  122. void NetServerMgr::send_data_to_server() const  
  123. {  
  124.     connect_server send_data;  
  125.     memset(&send_data, 0, sizeof(connect_server));  
  126.     sprintf_s(send_data.content, "%s""hello, this is client send to server");  
  127.   
  128.     std::cout << "send to server data is : " << send_data.content << std::endl;  
  129.   
  130.     RakNet::BitStream stream;  
  131.     stream.Write( ( RakNet::MessageID )ID_USER_PACKET_ENUM );  
  132.     stream.Write( msg_connect_server );  
  133.     stream.WriteBits((unsigned char *)&send_data , sizeof(connect_server) * 8 );  
  134.     net_peer->Send( &stream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, server_address, false );  
  135. }  
  136.   
  137. // 接收 server 回应的数据 并打印出来  
  138. void NetServerMgr::receive_data_from_server(const unsigned char *msg_data)  const  
  139. {  
  140.     connect_server_return *receive_data = (connect_server_return *)msg_data;  
  141.   
  142.     std::cout << "receive from server data is :" << receive_data->content_return << std::endl;  
  143. }  
#include "NetServerMgr.h"
#include "../../Source/RakPeerInterface.h"
#include "../../Source/RakNetTypes.h"
#include "../../Source/MessageIdentifiers.h"
#include "../../Source/BitStream.h"

#include <iostream>
#include "ServerClientMessage.h"
#include "ServerClientStruct.h"


RakNet::RakPeerInterface *net_peer;			//网络消息
RakNet::Packet *net_packet;					//网络消息包
RakNet::SystemAddress server_address;		//server 地址

NetServerMgr::NetServerMgr()
	: server_ip("localhost")
	, server_port(10001)
{

}

NetServerMgr::~NetServerMgr()
{

}

//初始化网络
void NetServerMgr::init_net_work() const
{
	//初始化网络消息
	net_peer = RakNet::RakPeerInterface::GetInstance();
	if (NULL == net_peer)
	{
		std::cout << "GetInstance failed" << std::endl;
		return;
	}

	int start_up = net_peer->Startup(1, &RakNet::SocketDescriptor(), 1);
	if (start_up > 0)
	{
		std::cout << "Startup failed" << std::endl;
		return;
	}

	//Connect 连接server
	//successful 返回 CONNECTION_ATTEMPT_STARTED
	bool rs = (net_peer->Connect(server_ip.c_str(), server_port, NULL, 0, 0) == RakNet::CONNECTION_ATTEMPT_STARTED);
	if (!rs)
	{
		std::cout << "connect server failed" << std::endl;
		return;
	}
}

//接收网络消息
void NetServerMgr::net_work_update()
{
	for (net_packet = net_peer->Receive(); net_packet; net_peer->DeallocatePacket(net_packet), net_packet = net_peer->Receive())
	{
		switch (net_packet->data[0])
		{
		case ID_REMOTE_DISCONNECTION_NOTIFICATION:
			std::cout << "Another client has disconnected" << std::endl;
			break;
		case ID_REMOTE_CONNECTION_LOST:
			std::cout << "Another client has lost the connection" << std::endl;
			break;
		case ID_REMOTE_NEW_INCOMING_CONNECTION:
			std::cout << "Another client has connected" << std::endl;
			break;
		//client连接上server后会触发
		case ID_CONNECTION_REQUEST_ACCEPTED:
			std::cout << "Our connection request has been accepted for server" << std::endl;
			server_address = net_packet->systemAddress;
			this->send_data_to_server();
			break;
		case ID_NEW_INCOMING_CONNECTION:
			std::cout << "A connection is incoming  " << std::endl;
			break;
		case ID_NO_FREE_INCOMING_CONNECTIONS:
			std::cout << "The server is full" << std::endl;
			break;
		case ID_DISCONNECTION_NOTIFICATION:
			std::cout << "A client has disconnected" << std::endl;
			break;
		case ID_CONNECTION_LOST:
			std::cout << "A client lost the connection  " << std::endl;
			break;
		case ID_USER_PACKET_ENUM:
			_process_server_message();				//用户自定义消息入口
			break;
		default:
			std::cout << "Message with identifier %d has arrived" << net_packet->data[0] << std::endl;
			break;
		}
	}
}

// server 发送过来的消息
void NetServerMgr::_process_server_message() const
{
	int message_id = 0;
	RakNet::BitStream bs_in(net_packet->data, net_packet->length, false);
	bs_in.IgnoreBytes(sizeof(RakNet::MessageID));
	bs_in.Read(message_id);

	unsigned char *msg_data = net_packet->data;
	msg_data += sizeof(unsigned long) + sizeof(unsigned char);
	switch (message_id)
	{
	case msg_connect_server_return:
		this->receive_data_from_server(msg_data);
		break;

	default:
		break;
	}
}

// 向 server 发送数据
void NetServerMgr::send_data_to_server() const
{
	connect_server send_data;
	memset(&send_data, 0, sizeof(connect_server));
	sprintf_s(send_data.content, "%s", "hello, this is client send to server");

	std::cout << "send to server data is : " << send_data.content << std::endl;

	RakNet::BitStream stream;
	stream.Write( ( RakNet::MessageID )ID_USER_PACKET_ENUM );
	stream.Write( msg_connect_server );
	stream.WriteBits((unsigned char *)&send_data , sizeof(connect_server) * 8 );
	net_peer->Send( &stream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, server_address, false );
}

// 接收 server 回应的数据 并打印出来
void NetServerMgr::receive_data_from_server(const unsigned char *msg_data) const
{
	connect_server_return *receive_data = (connect_server_return *)msg_data;

	std::cout << "receive from server data is :" << receive_data->content_return << std::endl;
}

Main.cpp
  1. #include "NetServerMgr.h"  
  2. #include <iostream>  
  3.   
  4. int main()  
  5. {  
  6.     NetServerMgr *p = new NetServerMgr;  
  7.   
  8.     p->init_net_work();  
  9.   
  10.     while (true)  
  11.     {  
  12.         p->net_work_update();  
  13.     }  
  14.       
  15.     delete p;  
  16.     p = NULL;  
  17.   
  18.     return 0;  
  19. }  
#include "NetServerMgr.h"
#include <iostream>

int main()
{
	NetServerMgr *p = new NetServerMgr;

	p->init_net_work();

	while (true)
	{
		p->net_work_update();
	}
	
	delete p;
	p = NULL;

	return 0;
}

运行程序的时候,需要将RakNet_DLL_Debug_Win32.dll放到exe所在的目录下面。开启server,再开启client测试下:




由于server和client其实代码都差不过,注释就写了server的,感觉还是比较详细了,要是想深入了解,可以使用的时候直接查看里面的api文档。

发送数据的时候,先添加raknet的消息类型(就是ID_USER_PACKET_ENUM),再添加我们自定义的(这里是struct),最后添加实际数据。

接受的时候,要先偏移掉raknet的消息类型,这里其实一个char的大小,再偏移掉自定义的枚举消息类型,这里其实是整形,就可以获得实际的传输数据。发送的封包和解包是一个逆向的过程。