ENet网络库教程翻译

ENet官网地址:http://enet.bespin.org


教程地址:http://enet.bespin.org/Tutorial.html#CreateServer


初始化:

使用enet时你需要include<enet/enet.h>,如果include<enet.h> 在某些系统中可能会造成一些文件名冲突。


在使用ENet之前,你必须调用enet_initialize()来初始化库。当程序退出时,你需要调用enet_deinitialize()这样库可以清理释放之前用过的资源。

#include <enet/enet.h>
int
main ( int argc, char ** argv)
{
if ( enet_initialize () != 0)
{
fprintf (stderr, "An error occurred while initializing ENet.\n");
return EXIT_FAILURE;
}
atexit ( enet_deinitialize);
...
...
...
}


创建一个ENet服务器


ENet的服务器使用enet_host_create()来创建的。你必须指定一个接收数据和接收新连接的地址和每个端的最大的连接数。你可以选择指定闯入传出带宽以位/秒为单位,这样ENet会尝试在已连接的对象中静态管理带宽资源而不是他的动态节流算法;两个参数都指定0的话将使得Enet完全依赖他的动态节流算法来管理带宽。

当使用完这个主机,主机可能需要用enet_host_destroy()来销毁。所有连接上这个主机的玩家都将被重制,主机使用的资源将被释放。

ENetAddress address;
ENetHost * server;
/* Bind the server to the default localhost. */
/* A specific host address can be specified by */
/* enet_address_set_host (& address, "x.x.x.x"); */
address.host = ENET_HOST_ANY;
/* Bind the server to port 1234. */
address.port = 1234;
server = enet_host_create (& address /* the address to bind the server host to */,
32 /* allow up to 32 clients and/or outgoing connections */,
2 /* allow up to 2 channels to be used, 0 and 1 */,
0 /* assume any amount of incoming bandwidth */,
0 /* assume any amount of outgoing bandwidth */);
if (server == NULL)
{
fprintf (stderr,
"An error occurred while trying to create an ENet server host.\n");
exit (EXIT_FAILURE);
}
...
...
...
enet_host_destroy(server);


创建一个ENet客户端


Enet的客户端同样也是用enet_host_create() 来创建,但是没有地址,特别是绑定主机。依照上面的例子客户端主机的带宽可能会指定。peer count控制连接其他同时打开的服务器主机的最大连接数。


ENetHost * client;
client = enet_host_create (NULL /* create a client host */,
1 /* only allow 1 outgoing connection */,
2 /* allow up 2 channels to be used, 0 and 1 */,
57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */,
14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */);
if (client == NULL)
{
fprintf (stderr,
"An error occurred while trying to create an ENet client host.\n");
exit (EXIT_FAILURE);
}
...
...
...
enet_host_destroy(client);


管理一个ENet主机

ENet使用轮询事件模型来通知程序员重大的事情。ENet主机使用 enet_host_service()来轮询事件,其中有个以毫秒为单位的时间参数将控制多久ENet轮询一次;如果参数是0,enet_host_service()将会立刻返回如果他没有事件分派的话。如果事件在指定的时间内被分发 enet_host_service()将会返回1。


当前ENet只有四种类型的事件

ENET_EVENT_TYPE_NONE 类型:如果没有事件在指定时间内发生将返回此类型

ENET_EVENT_TYPE_CONNECT 类型:当一个新的客户端主机连接上服务端主机或者当成功建立了与一个外部主机的连接时返回此类型。event数据结构中只有“peer”数据是有效的,并且包含了新连接的peer。

ENET_EVENT_TYPE_RECEIVE当数据包从连接的peer接收,返回此类型。“peer”数据域包含数据包的发送者,“channelID”是数据包发送的通道,“packet”是发送的数据包。当检查完它的内容后“packet”中的数据包必须用enet_packet_destroy()销毁。

ENET_EVENT_TYPE_DISCONNECT :当连接的peer显示的断开连接或者超时断开时返回此类型。事件数据结构中只有“peer”数据域是有效的并且包含失去连接的端口。断开连接的事件中只有“data”数据域是依然有效的并且必须显示的重制。

/* Wait up to 1000 milliseconds for an event. */
while ( enet_host_service (client, & event, 1000) > 0)
{
switch (event. type)
{
printf ( "A new client connected from %x:%u.\n",
event. peer -> address.host,
event. peer -> address.port);
/* Store any relevant client information here. */
event.peer -> data = "Client information";
break;
printf ( "A packet of length %u containing %s was received from %s on channel %u.\n",
event. packet -> dataLength,
event. packet -> data,
event. peer -> data,
event. channelID);
/* Clean up the packet now that we're done using it. */
break;
printf ( "%s disconected.\n", event. peer -> data);
/* Reset the peer's client information. */
event.peer -> data = NULL;
}
}
...
...
...

给ENet peer发送一个数据包


ENet中的数据包用enet_packet_create()创建,数据包的大小必须指定。可选择的,初始化数据可能会复制到数据包里。

某些标志可能也会应用在enet_packet_create()上来控制一些数据包特性:

ENET_PACKET_FLAG_RELIABLE 指定了数据包必须用可靠的数据传输。一个可靠的数据包必定可靠的 传输,一系列重试的尝试会进行直到数据包发送到的外部主机的验证消息被接收到了。如果一系列尝试后还是没有任何的答复,ENet将假定peer已经断开连接并且强制重制连接。如果标志没有指定,数据包将假定为一个不可靠的数据包,将不会有重试机制。

一个数据包可能会需要改变大小(扩张或者截取),使用enet_packet_resize().

一个数据包使用enet_peer_send()来发送到外部主机。enet_peer_send() 接收一个通道参数来发送数据包到指定的peer。一旦数据包使用ENet 的enet_peer_send()来处理,ENet将处理它的释放并且不需要使用 enet_packet_destroy()

也可以使用enet_host_broadcast()来发送数据包给所有链接到指定host peer上的peers通过指定的通道ID。

数据包队列将会发送enet_host_service()。另外,enet_host_flush()将发送数据包队列并且不分发它。


/* Create a reliable packet of size 7 containing "packet\0" */
ENetPacket * packet = enet_packet_create ( "packet",
strlen ( "packet") + 1,
/* Extend the packet so and append the string "foo", so it now */
/* contains "packetfoo\0" */
enet_packet_resize (packet, strlen ( "packetfoo") + 1);
strcpy (& packet -> data [strlen ( "packet")], "foo");
/* Send the packet to the peer over channel id 0. */
/* One could also broadcast the packet by */
/* enet_host_broadcast (host, 0, packet); */
enet_peer_send (peer, 0, packet);
...
...
...
/* One could just use enet_host_service() instead. */
enet_host_flush (host);

断开连接

peers使用enet_peer_disconnect()将会平缓的断开连接。一个断开连接的请求将会发送到外部主机,ENet将会等待来自远程主机的确认在完成断开之前。事件状态ENET_EVENT_TYPE_DISCONNECT 将会产生一旦断开成功。一旦在参数时间内没有应答peer将会强制断开

enet_peer_reset()将会简直快开一个peer,外部主机将不会得到断开的消息,将在外部主机上超时,没有事件生成。

ENetEvent event;
/* Allow up to 3 seconds for the disconnect to succeed
and drop any packets received packets.
/
while (enet_host_service (client, & event, 3000) > 0)
{
switch (event.type)
{
case ENET_EVENT_TYPE_RECEIVE:
enet_packet_destroy (event.packet);
break;
case ENET_EVENT_TYPE_DISCONNECT:
puts ("Disconnection succeeded.");
return;
...
...
...
}
}
/* We've arrived here, so the disconnect attempt didn't */
/* succeed yet. Force the connection down. */
enet_peer_reset (peer);
...
...
...

接到Enet主机

与远程主机的连接通过enet_host_connect()来初始化。它接收了一个远程的主机的地址为参数和一个分配给通讯的通道数量为参数来连接。如果N个通道被使用,那么序号是从0 - N-1,peer变量代表尝试连接的数量,null表示没有可用的peer,当连接成功,ENET_EVENT_TYPE_CONNECT 类型将被生成。如果连接超时或者各种原因失败,那么ENET_EVENT_TYPE_DISCONNECT类型会生成。

ENetAddress address;
ENetEvent event;
ENetPeer *peer;
/* Connect to some.server.net:1234. */
enet_address_set_host (& address, "some.server.net");
address.port = 1234;
/* Initiate the connection, allocating the two channels 0 and 1. */
peer = enet_host_connect (client, & address, 2, 0);
if (peer == NULL)
{
fprintf (stderr,
"No available peers for initiating an ENet connection.\n");
exit (EXIT_FAILURE);
}
/* Wait up to 5 seconds for the connection attempt to succeed. */
if ( enet_host_service (client, & event, 5000) > 0 &&
{
puts ( "Connection to some.server.net:1234 succeeded.");
...
...
...
}
else
{
/* Either the 5 seconds are up or a disconnect event was */
/* received. Reset the peer in the event the 5 seconds */
/* had run out without any significant event. */
enet_peer_reset (peer);
puts ( "Connection to some.server.net:1234 failed.");
}
...
...
...

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值