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

时间:2021-12-30 06:57:45

前言:

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

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

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


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


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


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


Server端通过

pPacket->systemAddress

获取到Client 的地址!


下面是完整的例子。


(1) Client 端


MyClient.h

#pragma once
#include <iostream>
#include "RakPeerInterface.h" // RakNet Peer
#include "RakNetTypes.h"
#include "MessageIdentifiers.h" // RakNet自定义消息枚举定义处
#include "BitStream.h" // RakNet消息包的Bit数据流

#define MAX_CLIENTS 10
#define SERVER_PORT 60000

enum ChatMessagesDefine
{// 自定义消息枚举值,消息ID
MSG_CHATWORD = ID_USER_PACKET_ENUM + 1, // 消息ID从RakNet定义的最后一个枚举开始
};

main.cpp

#include "MyClient.h"
#include <string>
#include <sstream>
#include <iostream>
#include "RakSleep.h"

using namespace std;

int main(void)
{

/*设置变量控制是否服务器已经返回操作结果*/
bool serverHaveSendBack=true;

RakNet::RakPeerInterface *pPeer = RakNet::RakPeerInterface::GetInstance();

RakNet::SocketDescriptor sd;
pPeer->Startup(1,&sd, 1);

std::string ipAddrStr;
cout<<"输入ip:";
cin>>ipAddrStr;

//作为客户端连接,连接到主机ip地址和端口号
pPeer->Connect(ipAddrStr.c_str(), SERVER_PORT, 0, 0);

string timeStrArray[6]={"10:00","11:59:58","19:59:58","20:04:58","20:29:58","23:59:55"};


float k = 0;
int i=0;
while(1)
{

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;

int chooseTime;

cin>>chooseTime;

std::string time=timeStrArray[chooseTime];

cout<<"将改变时间为:"<<time<<" !!"<<endl;

string timeStr=time;
string changeTimeCmd=string("time")+timeStr;

//给主机发送数据
RakNet::BitStream bsOut;
bsOut.Write((RakNet::MessageID)MSG_CHATWORD);
std::ostringstream format_messege;
format_messege <<timeStr; //输入信息到字符串流
bsOut.Write(format_messege.str().c_str());
pPeer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,RakNet::UNASSIGNED_SYSTEM_ADDRESS,true);
Sleep(500);

serverHaveSendBack=false;

/*等待服务器返回数据*/
RakNet::Packet* pPacket;
while(!serverHaveSendBack)
{
RakSleep(30);
for (pPacket=pPeer->Receive();pPacket;pPeer->DeallocatePacket(pPacket),pPacket=pPeer->Receive())
{
switch ( pPacket->data[0] )
{
case MSG_CHATWORD:
{
RakNet::RakString rs;
RakNet::BitStream bsIn(pPacket->data,pPacket->length,false);
bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
bsIn.Read(rs); //提取我自定的字符
istringstream input_str(rs.C_String());
string serverBackStr;
input_str>>serverBackStr;
cout<<"Server返回消息: "<<serverBackStr<<endl<<endl;
serverHaveSendBack=true;
}
break;
default:
break;
}
}

}

}

//断开连接,这个会给对方发送一个消息,告诉它要断开连接了。
pPeer->Shutdown(300);

RakNet::RakPeerInterface::DestroyInstance(pPeer);

return 0;
}

(2) Server 端


MyChatServer.h 

#pragma once

#include <iostream>
#include "RakPeerInterface.h" // RakNet Peer
#include "RakNetTypes.h"
#include "MessageIdentifiers.h" // RakNet自定义消息枚举定义处
#include "BitStream.h" // RakNet消息包的Bit数据流


#define MAX_CLIENTS 10
#define SERVER_PORT 60000

enum ChatMessagesDefine
{// 自定义消息枚举值,消息ID
MSG_CHATWORD = ID_USER_PACKET_ENUM + 1, // 消息ID从RakNet定义的最后一个枚举开始
};


main.cpp

#include "MyChatServer.h"
#include <string>
#include <iostream>
#include <sstream>
#include "RakNetTypes.h"

using namespace std;

int main()
{
//给服务器端创建一个实例
RakNet::RakPeerInterface* pPeer = RakNet::RakPeerInterface::GetInstance();
if ( NULL == pPeer )
{
std::cout << "RakNet::RakPeerInterface::GetInstance() Error!" << std::endl;
return -1;
}
else
{
std::cout << "———MyChatServer Init Success(C)———–" << std::endl;
}

RakNet::Packet* pPacket;
std::cout << "Start Server ……" << std::endl;
//启动服务器
pPeer->Startup( MAX_CLIENTS, &RakNet::SocketDescriptor( SERVER_PORT, 0 ), 1 );

//设置最大链接数
pPeer->SetMaximumIncomingConnections( MAX_CLIENTS );

//////////////////////////////////////////////////////////////////////////
while (1)
{
for ( pPacket = pPeer->Receive(); pPacket; pPeer->DeallocatePacket( pPacket ), pPacket = pPeer->Receive() )
{
switch ( pPacket->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" << std::endl;

RakNet::BitStream bsOut;
bsOut.Write( ( RakNet::MessageID )MSG_CHATWORD );
bsOut.Write("Hello world");
pPeer->Send( &bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, pPacket->systemAddress, false );
}
break;
case ID_NEW_INCOMING_CONNECTION:
{
std::cout << "A connection is incoming" << std::endl;
std::string clientIpAddr=pPacket->systemAddress.ToString(true);
std::string GUID=pPacket->guid.ToString();
UINT clientPort=pPacket->systemAddress.GetPort();
cout<<"clientIpAddr= "<<clientIpAddr<<" GUID= "<<GUID<<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 MSG_CHATWORD:
{
RakNet::RakString rs;
RakNet::BitStream bsIn( pPacket->data, pPacket->length, false );
bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
bsIn.Read(rs); //提取字符串
std::istringstream input_str(rs.C_String()); //存入字符串流
std::string timeStr;
input_str >>timeStr; //提取想要的变量

std::string changeTimeCmd=std::string("time ")+timeStr;

int a= system(changeTimeCmd.c_str());

std::cout << "时间改变为:"<<changeTimeCmd<< std::endl; //打印结果

//给主机发送数据
int connectState= pPeer->GetConnectionState(pPacket->guid);
RakNet::BitStream bsOut;
bsOut.Write((RakNet::MessageID)MSG_CHATWORD);
bsOut.Write("时间改变成功!");
pPeer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,pPacket->systemAddress,false);
}
break;

default:
std::cout << "Message with identifier %i has arrived" << pPacket->data[0] << std::endl;
break;
}
}
}

//////////////////////////////////////////////////////////////////////////
RakNet::RakPeerInterface::DestroyInstance( pPeer );
return 0;
}

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


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

转载请注明 http://blog.csdn.net/huutu   谢谢!