1. 首先下載Raknet的源代碼,我用的是4.0的,不是最新的,解壓后編譯DLL工程,編譯完成后進入解壓的根目錄下,進入Lib文件夾下找到RakNet_DLL_Debug_Win32.dll, RakNet_DLL_Debug_Win32.lib這兩個庫文件,並將其關聯到工程中。
2. 將解壓目錄下Source文件夾下的資源也管理到你的工程中
進行完上面兩步就將網絡庫配置完成,下面便開始服務器端與客戶端的程序編寫
// 服務器端程序
#include <string> #include <sstream> #include <iostream> #include "raknet/RakPeerInterface.h" #include "raknet/RakNetTypes.h" #include "raknet/MessageIdentifiers.h" // RakNet自定義消息枚舉定義處 #include "raknet/BitStream.h" // RakNet消息包的Bit數據流 #define MAX_CLIENTS 10 #define SERVER_PORT 60000 enum ChatMessagesDefine {// 自定義消息枚舉值,消息ID MSG_CHATWORD = ID_USER_PACKET_ENUM + 1, // 消息ID從RakNet定義的最后一個枚舉開始 }; // 服務器端程序 int _tmain(int argc, _TCHAR* argv[]) { // 給服務器端創建一個實例 RakNet::RakPeerInterface* pPeer = RakNet::RakPeerInterface::GetInstance(); if ( NULL == pPeer ) { std::cout << "RakNet::RakPeerInterface::GetInstance() Error!" << std::endl << std::endl; return -1; } else { std::cout << "--------- MyServer Init Success -----------" << std::endl << std::endl; } RakNet::Packet* pPacket; std::cout << "Start Server ......" << std::endl << 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 << "Our connection request has been accepted !" << std::endl; RakNet::BitStream bsOut; bsOut.Write( ( RakNet::MessageID )MSG_CHATWORD ); bsOut.Write("Hello world ! I'm successed ! Congratulations !"); pPeer->Send( &bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, pPacket->systemAddress, false ); } 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 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()); //存入字符串流 double v, h; input_str >> v >> h; //提取想要的變量 std::cout << v << " " << h << std::endl; //打印結果 } break; default: std::cout << "Message with identifier %i has arrived !" << pPacket->data[ 0 ] << std::endl; break; } } } ////////////////////////////////////////////////////////////////////////// RakNet::RakPeerInterface::DestroyInstance( pPeer ); /* //創建一個實例 RakNet::RakPeerInterface *server = RakNet::RakPeerInterface::GetInstance(); //創建套接字描述,也就是指定一個通信端口(UDP無監聽) RakNet::SocketDescriptor socketDescriptor; socketDescriptor.port = 30050; //啟動服務器端 bool b = server->Startup(2, &socketDescriptor, 1 )== RakNet::RAKNET_STARTED; //如果沒有報錯,服務端啟動成功了。 RakAssert(b); if ( b ) { printf( "服務器啟動成功!\n\n等待客戶端的請求......\n\n" ); } else { printf( "服務器啟動失敗!\n\n請重新啟動服務器!\n\n" ); } //設置最大連接數(此連接並不等同TCP的連接!),這一步必須設置,否則會出現客戶端調用Connect失敗 server->SetMaximumIncomingConnections(2); //接下來就是處理數據發送接收的部分了 while( 1 ) { RakNet::Packet * packet = server->Receive(); if( packet ) { switch( packet->data[0] ) { //用戶自定義數據包的接收處理,此處顯示接到的數據包內容。其他消息的處理可以同樣用case語句 case ID_USER_PACKET_ENUM: printf("接收到自定義數據,內容: %s\n\n", packet->data ); break; default: break; } } } */ return 0; }
// 客戶端程序
#include <string> #include <sstream> #include <iostream> #include "raknet/RakPeerInterface.h" #include "raknet/RakNetTypes.h" #include "raknet/MessageIdentifiers.h" #include "raknet/BitStream.h" #define MAX_CLIENTS 10 #define SERVER_PORT 60000 enum ChatMessagesDefine {// 自定義消息枚舉值,消息ID MSG_CHATWORD = ID_USER_PACKET_ENUM + 1, // 消息ID從RakNet定義的最后一個枚舉開始 }; // 客戶端程序 int _tmain(int argc, _TCHAR* argv[]) { double v = 1000.023; double h = 10023.23; RakNet::RakPeerInterface *peer = RakNet::RakPeerInterface::GetInstance(); RakNet::SocketDescriptor sd; peer->Startup(1, &sd, 1); // 作為客戶端連接,連接到主機ip地址和端口號 peer->Connect("127.0.0.1", SERVER_PORT, 0, 0); float k = 0; int i = 0; for ( i = 0; i < 10; i++ ) { // 給主機發送數據 RakNet::BitStream bsOut; bsOut.Write( (RakNet::MessageID)MSG_CHATWORD ); std::ostringstream format_messege; format_messege << v++ << " " << h++; // 輸入信息到字符串流,用空格隔開,此處為飛行器速度高度V, h為double型 // bsOut.Write("hello"); std::string ss = format_messege.str(); // str()返回的是臨時對象 bsOut.Write( ss.c_str() ); peer->Send( &bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, RakNet::UNASSIGNED_SYSTEM_ADDRESS, true ); Sleep( 500 ); } RakNet::Packet * packet; while( 1 ) { packet = peer->Receive(); if( packet ) { // 當接收到的消息的第一個字節的數據為 ID_CONNECTION_REQUEST_ACCEPTED 才表示服務端接受了連接請求!!! if( packet->data[0] == MSG_CHATWORD ) { RakNet::RakString rs; RakNet::BitStream bsIn( packet->data, packet->length, false ); bsIn.IgnoreBytes(sizeof(RakNet::MessageID)); bsIn.Read( rs ); printf("server return = %s", rs.C_String() ); } } } //斷開連接,這個會給對方發送一個消息,告訴它要斷開連接了。 peer->Shutdown( 300 ); RakNet::RakPeerInterface::DestroyInstance(peer); /* RakNet::RakPeerInterface *client = RakNet::RakPeerInterface::GetInstance(); RakNet::SocketDescriptor socketDescriptor; socketDescriptor.port = 0; client->Startup(1, &socketDescriptor, 1 ); // 客戶端連接服務端,判斷返回值和RakNet::CONNECTION_ATTEMPT_STARTED是否相等, // 相等只是代表請求投遞成功,並不意味着服務端接收了連接請求 bool rs = ( client->Connect("127.0.0.1", 30050, NULL, 0, 0) == RakNet::CONNECTION_ATTEMPT_STARTED ); // 數據包 RakNet::Packet *packet; bool bIsConn = false; // 循環接收來自服務端的消息 while(1) { packet = client->Receive(); if( packet ) { // 當接收到的消息的第一個字節的數據為 ID_CONNECTION_REQUEST_ACCEPTED 才表示服務端接受了連接請求!!! if( packet->data[0] == ID_CONNECTION_REQUEST_ACCEPTED ) { bIsConn = true; printf("服務器端受理了客戶端的請求!\n\n"); char flag = (char)ID_USER_PACKET_ENUM; char buffer[ ] = "這是來自客戶端的消息"; buffer[ 0 ] = flag; //連接ok后發送一個字符串到服務端 uint32_t sendrs = client->Send( (const char*)buffer, strlen(buffer)+1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, RakNet::UNASSIGNED_SYSTEM_ADDRESS, true ); printf("服務器端返回來的消息: %d\n",sendrs); } //如果沒有連接成功,則繼續連接,直到服務端返回的信息告訴我們連接成功了 if( !bIsConn ) { printf("連接服務器失敗!\n"); client->Connect("127.0.0.1", 30050, NULL, 0, 0); } } } */ system( "pause"); return 0; }
ps: 下面是將網絡庫關聯到你的工程中
1.右鍵工程--》屬性--》c/c++ --》常規--》"附加包含目錄",將源文件和上面的兩個文件包含進去
2.右鍵工程--》屬性--》鏈接器 --》常規--》"附加包含目錄",將源文件和上面的兩個文件包含進去
3.右鍵工程--》屬性--》鏈接器 --》輸入--》"附加依賴項",添加 RakNet_DLL_Debug_Win32.lib 庫