[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