可靠的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();
}

转载于:https://www.cnblogs.com/toosuo/archive/2011/12/13/2286232.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值