RakNet Client和公网Server通信 例子 -- 修改远程电脑时间

前言:

很多游戏引擎都是不带网络操作的,比如Cocos2d-x ,那我们只好自己去写或者使用现有的,技术有限的我们只能用现有的了。

RakNet是一个开源的C语言网络操作库,被广泛应用于各种网络程序中,当然我这里只关注手机网络游戏。。。。

这算是RakNet的入门一个例子。


本文适合对RakNet有一定了解的朋友


Client 可以直接指定Server 端的IP地址进行连接,从而发送消息、数据到服务端。但是服务端接收到客户端的消息后怎么回复客户端?


其实Server端和Client端发送消息数据都是同样的操作,只是获取消息目的地址的方式不一样。


Server端通过

[cpp]  view plain copy
  1. pPacket->systemAddress  

获取到Client 的地址!


下面是完整的例子。


(1) Client 端


MyClient.h 

[cpp]  view plain copy
  1. #pragma once  
  2. #include <iostream>  
  3. #include "RakPeerInterface.h"   // RakNet Peer  
  4. #include "RakNetTypes.h"        
  5. #include "MessageIdentifiers.h" // RakNet自定义消息枚举定义处  
  6. #include "BitStream.h"         // RakNet消息包的Bit数据流  
  7.   
  8. #define MAX_CLIENTS 10  
  9. #define SERVER_PORT 60000  
  10.   
  11. enum ChatMessagesDefine  
  12. {// 自定义消息枚举值,消息ID  
  13.     MSG_CHATWORD = ID_USER_PACKET_ENUM + 1,        // 消息ID从RakNet定义的最后一个枚举开始  
  14. };  

main.cpp

[cpp]  view plain copy
  1. #include "MyClient.h"  
  2. #include <string>  
  3. #include <sstream>  
  4. #include <iostream>  
  5. #include "RakSleep.h"  
  6.   
  7. using namespace std;  
  8.   
  9. int main(void)  
  10. {  
  11.   
  12.     /*设置变量控制是否服务器已经返回操作结果*/  
  13.     bool serverHaveSendBack=true;  
  14.   
  15.     RakNet::RakPeerInterface *pPeer = RakNet::RakPeerInterface::GetInstance();  
  16.   
  17.     RakNet::SocketDescriptor sd;  
  18.     pPeer->Startup(1,&sd, 1);  
  19.   
  20.     std::string ipAddrStr;  
  21.     cout<<"输入ip:";  
  22.     cin>>ipAddrStr;  
  23.   
  24.     //作为客户端连接,连接到主机ip地址和端口号  
  25.     pPeer->Connect(ipAddrStr.c_str(), SERVER_PORT, 0, 0);  
  26.   
  27.     string timeStrArray[6]={"10:00","11:59:58","19:59:58","20:04:58","20:29:58","23:59:55"};  
  28.   
  29.   
  30.     float k = 0;  
  31.     int i=0;  
  32.     while(1)  
  33.     {  
  34.   
  35.         cout<<"改变时间:[0] 10:00  -  [1] 11:59:58  -  [2] 19:59:58  - [3] 20:04:58   [4]  20:29:58  [5] 23:59:55"<<endl;  
  36.   
  37.         int chooseTime;  
  38.   
  39.         cin>>chooseTime;  
  40.   
  41.         std::string time=timeStrArray[chooseTime];  
  42.   
  43.         cout<<"将改变时间为:"<<time<<"  !!"<<endl;  
  44.   
  45.         string timeStr=time;  
  46.         string changeTimeCmd=string("time")+timeStr;  
  47.   
  48.         //给主机发送数据  
  49.         RakNet::BitStream bsOut;  
  50.         bsOut.Write((RakNet::MessageID)MSG_CHATWORD);  
  51.         std::ostringstream format_messege;  
  52.         format_messege <<timeStr;    //输入信息到字符串流  
  53.         bsOut.Write(format_messege.str().c_str());  
  54.         pPeer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,RakNet::UNASSIGNED_SYSTEM_ADDRESS,true);  
  55.         Sleep(500);  
  56.   
  57.         serverHaveSendBack=false;  
  58.   
  59.         /*等待服务器返回数据*/  
  60.         RakNet::Packet* pPacket;  
  61.         while(!serverHaveSendBack)  
  62.         {  
  63.             RakSleep(30);  
  64.             for (pPacket=pPeer->Receive();pPacket;pPeer->DeallocatePacket(pPacket),pPacket=pPeer->Receive())  
  65.             {  
  66.                 switch ( pPacket->data[0] )  
  67.                 {  
  68.                 case MSG_CHATWORD:  
  69.                     {  
  70.                         RakNet::RakString rs;  
  71.                         RakNet::BitStream bsIn(pPacket->data,pPacket->length,false);  
  72.                         bsIn.IgnoreBytes(sizeof(RakNet::MessageID));  
  73.                         bsIn.Read(rs); //提取我自定的字符  
  74.                         istringstream input_str(rs.C_String());  
  75.                         string serverBackStr;  
  76.                         input_str>>serverBackStr;  
  77.                         cout<<"Server返回消息: "<<serverBackStr<<endl<<endl;  
  78.                         serverHaveSendBack=true;  
  79.                     }  
  80.                     break;  
  81.                 default:  
  82.                     break;  
  83.                 }  
  84.             }  
  85.   
  86.         }  
  87.   
  88.     }  
  89.   
  90.     //断开连接,这个会给对方发送一个消息,告诉它要断开连接了。  
  91.     pPeer->Shutdown(300);  
  92.   
  93.     RakNet::RakPeerInterface::DestroyInstance(pPeer);  
  94.   
  95.     return 0;  
  96. }  

(2) Server 端


MyChatServer.h 

[cpp]  view plain copy
  1. #pragma once  
  2.   
  3. #include <iostream>  
  4. #include "RakPeerInterface.h"   // RakNet Peer  
  5. #include "RakNetTypes.h"         
  6. #include "MessageIdentifiers.h" // RakNet自定义消息枚举定义处  
  7. #include "BitStream.h"          // RakNet消息包的Bit数据流  
  8.   
  9.   
  10. #define MAX_CLIENTS 10  
  11. #define SERVER_PORT 60000  
  12.   
  13. enum ChatMessagesDefine  
  14. {// 自定义消息枚举值,消息ID  
  15.     MSG_CHATWORD = ID_USER_PACKET_ENUM + 1,        // 消息ID从RakNet定义的最后一个枚举开始  
  16. };  

main.cpp

[cpp]  view plain copy
  1. #include "MyChatServer.h"  
  2. #include <string>  
  3. #include <iostream>  
  4. #include <sstream>  
  5. #include "RakNetTypes.h"    
  6.   
  7. using namespace std;  
  8.   
  9. int main()  
  10. {  
  11.     //给服务器端创建一个实例  
  12.     RakNet::RakPeerInterface* pPeer = RakNet::RakPeerInterface::GetInstance();  
  13.     if ( NULL == pPeer )  
  14.     {  
  15.         std::cout << "RakNet::RakPeerInterface::GetInstance() Error!" << std::endl;  
  16.         return -1;  
  17.     }  
  18.     else  
  19.     {  
  20.         std::cout << "———MyChatServer Init Success(C)———–" << std::endl;  
  21.     }  
  22.   
  23.     RakNet::Packet* pPacket;  
  24.     std::cout << "Start Server ……" << std::endl;  
  25.     //启动服务器  
  26.     pPeer->Startup( MAX_CLIENTS, &RakNet::SocketDescriptor( SERVER_PORT, 0 ), 1 );  
  27.   
  28.     //设置最大链接数  
  29.     pPeer->SetMaximumIncomingConnections( MAX_CLIENTS );  
  30.   
  31.     //  
  32.     while (1)  
  33.     {  
  34.         for ( pPacket = pPeer->Receive(); pPacket; pPeer->DeallocatePacket( pPacket ), pPacket = pPeer->Receive() )  
  35.         {  
  36.             switch ( pPacket->data[0] )  
  37.             {  
  38.             case ID_REMOTE_DISCONNECTION_NOTIFICATION:  
  39.                 std::cout << "Another client has disconnected" << std::endl;  
  40.                 break;  
  41.             case ID_REMOTE_CONNECTION_LOST:  
  42.                 std::cout << "Another client has lost the connection"<< std::endl;  
  43.                 break;  
  44.             case ID_REMOTE_NEW_INCOMING_CONNECTION:  
  45.                 std::cout << "Another client has connected" << std::endl;  
  46.                 break;  
  47.             case ID_CONNECTION_REQUEST_ACCEPTED:  
  48.                 {  
  49.                     std::cout << "Our connection request has been accepted" << std::endl;  
  50.   
  51.                     RakNet::BitStream bsOut;  
  52.                     bsOut.Write( ( RakNet::MessageID )MSG_CHATWORD );  
  53.                     bsOut.Write("Hello world");  
  54.                     pPeer->Send( &bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, pPacket->systemAddress, false );  
  55.                 }  
  56.                 break;  
  57.             case ID_NEW_INCOMING_CONNECTION:  
  58.                 {  
  59.                     std::cout << "A connection is incoming" << std::endl;  
  60.                     std::string clientIpAddr=pPacket->systemAddress.ToString(true);  
  61.                     std::string GUID=pPacket->guid.ToString();  
  62.                     UINT clientPort=pPacket->systemAddress.GetPort();  
  63.                     cout<<"clientIpAddr= "<<clientIpAddr<<"  GUID= "<<GUID<<endl;  
  64.                 }  
  65.                 break;  
  66.             case ID_NO_FREE_INCOMING_CONNECTIONS:  
  67.                 std::cout << "The server is full"<< std::endl;  
  68.                 break;  
  69.             case ID_DISCONNECTION_NOTIFICATION:  
  70.                 std::cout << "A client has disconnected"<< std::endl;  
  71.                 break;  
  72.             case ID_CONNECTION_LOST:  
  73.                 std::cout << "A client lost the connection" << std::endl;  
  74.                 break;  
  75.   
  76.                 //用户自定义数据包  
  77.             case MSG_CHATWORD:  
  78.                 {  
  79.                     RakNet::RakString rs;  
  80.                     RakNet::BitStream bsIn( pPacket->data, pPacket->length, false );  
  81.                     bsIn.IgnoreBytes(sizeof(RakNet::MessageID));  
  82.                     bsIn.Read(rs);    //提取字符串  
  83.                     std::istringstream input_str(rs.C_String()); //存入字符串流  
  84.                     std::string timeStr;  
  85.                     input_str >>timeStr; //提取想要的变量  
  86.   
  87.                     std::string changeTimeCmd=std::string("time ")+timeStr;  
  88.   
  89.                     int a= system(changeTimeCmd.c_str());  
  90.   
  91.                     std::cout << "时间改变为:"<<changeTimeCmd<< std::endl; //打印结果  
  92.   
  93.                     //给主机发送数据  
  94.                     int connectState= pPeer->GetConnectionState(pPacket->guid);  
  95.                     RakNet::BitStream bsOut;  
  96.                     bsOut.Write((RakNet::MessageID)MSG_CHATWORD);  
  97.                     bsOut.Write("时间改变成功!");  
  98.                     pPeer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,pPacket->systemAddress,false);  
  99.                 }  
  100.                 break;  
  101.   
  102.             default:  
  103.                 std::cout << "Message with identifier %i has arrived" << pPacket->data[0] << std::endl;  
  104.                 break;  
  105.             }  
  106.         }  
  107.     }  
  108.   
  109.     //  
  110.     RakNet::RakPeerInterface::DestroyInstance( pPeer );  
  111.     return 0;  
  112. }  

最后是程序运行的测试结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值