[ENet-discuss] Greetings, folks.
Anthony Goins
scapegoat at messiah.ath.cx
Wed May 26 01:37:57 PDT 2004
Howdy, first let me introduce myself. I am Anthony and a new
subscriber(really, I am. :p). I am a crappy programmer that just
recently started messing with ENet..
First let me thank you for a nifty networking library, it's pretty handy.
Anyways, I kinda got some basic stuff done with my server(after switching
from just using TCP to ENet... Anyways, when it comes to socket handling
and that type of stuff I am limited to basic select servers and using
read/write for sending text to and from the server to a telnet client(MUDs
anyone?).. So I am really just touching the surface with all this
networking/socket stuff..
I was looking for suggestions and or comments of the code I have so far, I
haven't actually got too much done I am a little uncertain about things.
I have a few functions I will show in a minute, one just initializes enet
while the other is the server loop which does all the main handling of
stuff.. I was wondering if I was going about this wrong or if there was a
better way of doing this.. Also I was wondering if anyone knew of any
other tutorials with ENet and or some working example programs people have
wrote to help us nubs(n00bs, newbs, newbies.. :p) get a better
understanding of ENet.. I have looked over the code and kinda have an
idea but it's a little overwhelming because now I have to deal with server
and client handling.. As before I just did the server stuff and telnet
already did the rest. :p blah I am babbling, hears the code, The full
server can be downloaded from http://messiah.ath.cx/scapegoat/as.tgz
It's not really open source right now, I am still trying to decided on
ENet or just going ahead with using TCP(which I have a better grasp
with).. Anyways, here's the socket.c file of the server..
Also, before I show the code let me apologize if this is too long, I don't
remember reading anything about that while signing up but it is 1:40 in
the morning atm..
ENetAddress address;
ENetHost * server;
ENetEvent event;
CLIENT * client_free = NULL;
CLIENT * client_list = NULL;
extern bool server_down;
/*
* Initialize the networking, setup the server.
*/
void init_net(int port)
{
/*
* This looks better on startup if logging is not set.. :p
*/
puts("\n");
/*
* We need to initialize ENet if we are to do anything
* so we call this function
*/
if (enet_initialize () != 0)
error_sys(NETLOG, "An error occurred while initializing ENet.");
else
Log(NETLOG, "ENet Initialized.");
/*
* Free up the ENet data on program exit.
*/
atexit(enet_deinitialize);
/*
* 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;
address.port = port; /* Bind the server to port 1234. */
/*
* Create the listening server.
* the second argument is maximum connections
* the second is maxincomming bandwidth, third is oposite.
*/
server = enet_host_create(&address, 10 * 100, 0, 0);
if (server == NULL)
error_sys(NETLOG, "An error occurred while trying to create an ENet server host.\n");
else
Log(NETLOG, "Aalyreth Server bound and listening on %x:%u", htonl(address.host), address.port);
}
/*
* The main server loop, be carefull.
* We don't want to overlaod the server and cause a lot
* of lag.. This controls everything, don't touch unless
* you know what you are doing.
*/
void server_loop(void)
{
CLIENT *client;
struct timeval last_time, new_time;
long secs, usecs;
/* set this for the first loop */
gettimeofday(&last_time, NULL);
while(!server_down)
{
/* Wait up to 1000 milliseconds for an event. */
while(enet_host_service(server, &event, 1000) > 0)
{
switch (event.type)
{
case ENET_EVENT_TYPE_NONE:
/* Nothing needs to be done here I suppose.. */
break;
case ENET_EVENT_TYPE_CONNECT:
Log(NETLOG, "A new client connected from %x:%u.\n", event.peer->address.host, event.peer->address.port);
if ((client = new_client(event.peer)) == NULL)
Log(NETLOG, "New client could not be allocated.");
/* Store any relevant client information here. */
event.peer->data = client;
break;
case ENET_EVENT_TYPE_RECEIVE:
Log(NETLOG, "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. */
enet_packet_destroy(event.packet);
break;
case ENET_EVENT_TYPE_DISCONNECT:
Log(NETLOG, "%s disconected.\n", event.peer->data);
/* We've arrived here, so the disconnect attempt didn't succeed yet.
* Force the connection down.
*/
enet_peer_reset(&event.peer[0]);
/* Reset the peer's client information. */
event.peer->data = NULL;
break;
}
}
/* call the event queue */
heartbeat();
/*
* Here we sleep out the rest of the pulse, thus forcing
* the server to run at PULSES_PER_SECOND pulses each second.
*/
gettimeofday(&new_time, NULL);
/* get the time right now, and calculate how long we should sleep */
usecs = (int) (last_time.tv_usec - new_time.tv_usec) + 1000000 / PULSES_PER_SECOND;
secs = (int) (last_time.tv_sec - new_time.tv_sec);
/*
* Now we make sure that 0 <= usecs < 1.000.000
*/
while (usecs < 0)
{
usecs += 1000000;
secs -= 1;
}
while (usecs >= 1000000)
{
usecs -= 1000000;
secs += 1;
}
/* if secs < 0 we don't sleep, since we have encountered a laghole */
if (secs > 0 || (secs == 0 && usecs > 0))
{
struct timeval sleep_time;
sleep_time.tv_usec = usecs;
sleep_time.tv_sec = secs;
if (select(0, NULL, NULL, NULL, &sleep_time) < 0)
continue;
}
/* reset the last time we where sleeping */
gettimeofday(&last_time, NULL);
}
}
/*
* Allocate memory, initialize and link a new
* connecting client.
*/
CLIENT *new_client(ENetPeer *peer)
{
CLIENT *client;
NEW_ITEM(client_free, client);
client->peer = peer;
LINK(client_list, client);
return client;
}
/*
* Send a packet to a specific client.
*
* type = type of packet to send
* client = the client to send to
* channel = the specific channel to deliver on
* reliable = if TRUE, send reliable, if FALSE assumed unreliable
*/
void send_packet(int type, CLIENT *client, int channel, bool reliable)
{
ENetPacket * packet = enet_packet_create(client->outbuf,
strlen(client->outbuf) + 1,
reliable ? ENET_PACKET_FLAG_RELIABLE : 0);
enet_peer_send(client->peer, channel, packet);
enet_host_flush(server);
}
/*
* Broadcast a message to everyone min_level and above.
*
* type = message type
* channel = channel to deliver on.
* min_level = min level to get the message delivered to.
* msg = message to be delivered, can have attributes.
*/
void broadcast_message(int type, int channel, sh_int min_level, char *msg, ...)
{
va_list ptr;
ENetPacket *packet;
char txt[512];
va_start(ptr, msg);
vsprintf(msg, (char *)txt, ptr);
va_end(ptr);
packet = enet_packet_create(msg, strlen(msg) + 1, ENET_PACKET_FLAG_RELIABLE);
enet_host_broadcast(server, channel, packet);
enet_host_flush(server);
}
...
Anyways, any suggestions for that? Thanks for any input at all.
Kind Regards,
Anthony
More information about the ENet-discuss
mailing list