zoukankan      html  css  js  c++  java
  • 可靠的UDP编程(ENET库)

    大家都知道UDP这个东西太不可靠了,存在着乱序,丢包,包重复等缺点,但它的速度快,包有界等优点,但在实际编程中要自己处理乱序啊之类的问题会发疯的。也许大家说用TCP就得了,第一点TCP的速度比较慢,第二个TCP是一个数据流一样的东西,我们要传数据的话还得处理数据的分界问题,也挺麻烦的。

        针对这个问题,ENET这个库实现了一个性能介于TCP与UDP之间,完成可靠(不丢包,按序),保持数据的分界的优点。编程起来也挺方便的。下载到http://enet.bespin.org/SourceDistro.html,目前最新版本是1.2,然后按照说明编译出库出来。

        使用ENET库就可以实际可靠的UDP编程,一个简单的例子如下:

    ///////服务器

    #include <iostream>
    #include <enet/enet.h>
    using namespace std;

    void main()
    {
    //初始化enet库
    if(enet_initialize())
    {
         cout <<"初始化失败" <<endl;
         return;
    }

    //下面创建服务器
    ENetAddress address;
    address.host=ENET_HOST_ANY;
    address.port=1234;

    ENetHost *server;
    server=enet_host_create(&address, //主机地址
                                               64,        //允许的连接数
                                                0,
                                               0);        //自动管理带宽
    if(server==NULL)
    {
         cout <<"创建主机对象失败" <<endl;
         enet_deinitialize();
        return;
    }


    //下面开始收数据等
    ENetEvent event;
    while(enet_host_service(server,&event,5000)>=0)
    {
        if(event.type==ENET_EVENT_TYPE_CONNECT) //有客户机连接成功
         {
          static unsigned int num=0;
          ENetAddress remote=event.peer->address; //远程地址
          char ip[256];
          enet_address_get_host_ip(&remote,ip,256);
          cout <<"ip:" <<ip <<" 已经连接,序号:" <<num <<endl;
          event.peer->data=(void*)num++;
        }
         else if(event.type==ENET_EVENT_TYPE_RECEIVE) //收到数据
         {
          cout <<"收到序号" <<event.peer->data <<"的数据,从" <<event.channelID <<"通道发送" <<endl;
          cout <<"数据大小:" <<event.packet->dataLength <<endl;
          cout <<"数据:" <<(char*)event.packet->data <<endl;
          enet_packet_destroy(event.packet);    //注意释放空间
          cout <<endl;
         }
         else if(event.type==ENET_EVENT_TYPE_DISCONNECT) //失去连接
         {
          cout <<"序号" <<event.peer->data <<"远程已经关闭连接" <<endl;
        }
    }

    enet_deinitialize();
    }

    ///////客户端

    #include <iostream>
    #include <enet/enet.h>
    using namespace std;

    void main()
    {
    //初始化enet库
    if(enet_initialize())
    {
       cout <<"初始化失败" <<endl;
       return;
    }

    //创建本地HOST对象
    ENetHost *client=enet_host_create(NULL,
               1,   //只允许连接一个服务器
               0,
               0);
    if(client==NULL)
    {
       cout <<"创建客户端失败" <<endl;
       return;
    }


    //连接到服务器
    ENetAddress svraddr;
    enet_address_set_host(&svraddr,"127.0.0.1");
    svraddr.port=1234;

    ENetPeer *server=enet_host_connect(client,&svraddr,3); //client连接到svraddr对象,共分配三个通道
    if(server==NULL)
    {
       cout <<"连接服务器失败" <<endl;
       return;
    }

    ENetEvent event;
    //连接成功后必须调用enet_host_service来最终确认
    if (enet_host_service (client, &event5000) > 0 &&
            event.type == ENET_EVENT_TYPE_CONNECT)
        {
            cout <<"连接服务器成功" <<endl;
        }
        else
        {
            enet_peer_reset (server);
            cout <<"连接服务器失败" <<endl;
       return;
        }
       

    //下面开始发数据
    ENetPacket *packet=enet_packet_create(NULL,78,ENET_PACKET_FLAG_RELIABLE); //创建包
    strcpy((char*)packet->data,"hi,哈哈");
    enet_peer_send(server,1,packet);

    ENetPacket *packet1=enet_packet_create(NULL,86,ENET_PACKET_FLAG_RELIABLE); //创建包
    strcpy((char*)packet1->data,"你好啊,呵呵");
    enet_peer_send(server,2,packet1);

    enet_host_flush (client); //必须使用这个函数或是enet_host_service来使数据发出去


    //关闭连接
    enet_peer_disconnect (server,0);
    //等待关闭成功
    while (enet_host_service (client, &event5000)>0)
        {
            switch (event.type)
            {
       case ENET_EVENT_TYPE_RECEIVE:
                enet_packet_destroy (event.packet);
                break;

            case ENET_EVENT_TYPE_DISCONNECT:
                cout <<"已经成功断开连接" <<endl;
        enet_deinitialize();
                return;
            }
        }

    //这里就是关闭失败,强制重置
    enet_peer_reset(server);
    cout <<"强制重置" <<endl;

    enet_deinitialize();
    }

  • 相关阅读:
    [MacOS]Sublime text3 安装(一)
    [RHEL8]开启BBR
    PAT Advanced 1136 A Delayed Palindrome (20分)
    PAT Advanced 1144 The Missing Number (20分)
    PAT Advanced 1041 Be Unique (20分)
    PAT Advanced 1025 PAT Ranking (25分)
    PAT Advanced 1022 Digital Library (30分)
    PAT Advanced 1019 General Palindromic Number (20分)
    PAT Advanced 1011 World Cup Betting (20分)
    PAT Advanced 1102 Invert a Binary Tree (25分)
  • 原文地址:https://www.cnblogs.com/toosuo/p/2286232.html
Copyright © 2011-2022 走看看