可靠的UDP编程(ENET库)

可靠的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 namespacestd;

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

// 下面创建服务器
ENetAddressaddress;
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) // 有客户机连接成功
{
staticunsigned intnum= 0;
ENetAddressremote= event.peer->address; // 远程地址
charip[ 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 namespacestd;

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

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


// 连接到服务器
ENetAddresssvraddr;
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,& event, 5000)> 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,& event, 5000)> 0)
{
switch( event.type)
{
caseENET_EVENT_TYPE_RECEIVE:
enet_packet_destroy( event.packet);
break;

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

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

enet_deinitialize();
}

你可能感兴趣的:(UDP)