Raknet实现的简单服务器与客户端的交互

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 库

 

你可能感兴趣的:(服务器)