diff options
author | eihrul <eihrul> | 2004-10-20 17:17:51 +0000 |
---|---|---|
committer | eihrul <eihrul> | 2004-10-20 17:17:51 +0000 |
commit | 3010e46b47c36a25f44c80b31daaf887ab1d8de5 (patch) | |
tree | f64bced38da8159f0eb70a09eb8863a417d59ef5 /docs | |
download | enet-3010e46b47c36a25f44c80b31daaf887ab1d8de5.tar.gz enet-3010e46b47c36a25f44c80b31daaf887ab1d8de5.zip |
Initial revision
Diffstat (limited to 'docs')
-rwxr-xr-x | docs/FAQ.dox | 24 | ||||
-rwxr-xr-x | docs/design.dox | 126 | ||||
-rwxr-xr-x | docs/install.dox | 37 | ||||
-rwxr-xr-x | docs/license.dox | 26 | ||||
-rwxr-xr-x | docs/mainpage.dox | 84 | ||||
-rwxr-xr-x | docs/tutorial.dox | 349 |
6 files changed, 646 insertions, 0 deletions
diff --git a/docs/FAQ.dox b/docs/FAQ.dox new file mode 100755 index 0000000..484b818 --- /dev/null +++ b/docs/FAQ.dox @@ -0,0 +1,24 @@ +/** + @page FAQ Frequently Answered Questions + +@section Q1 Is ENet thread safe? + +ENet does not use any significant global variables, the vast majority +of state is encapsulated in the ENetHost structure. As such, as long +as the application guards access to this structure, then ENet should +operate fine in a multithreaded environment. + +@section Q2 Isn't ENet just re-inventing TCP?! What's the point? + +In a perfect world, that would be true. But as many have found, using +TCP either in lieu of or in conjunction with UDP can lead to all kinds +of nightmares. TCP is a good, solid protocol, however it simply isn't +up to the task of real-time games. Too much of TCP's implementation +dictates a policy that isn't practical for games. If you want to use +TCP, then do so -- this library is for people that either don't want +to use TCP or have tried and ended up being discouraged with the +performance. + +*/ + + diff --git a/docs/design.dox b/docs/design.dox new file mode 100755 index 0000000..daed221 --- /dev/null +++ b/docs/design.dox @@ -0,0 +1,126 @@ +/** +@page Features Features and Architecture + +ENet evolved specifically as a UDP networking layer for the +multiplayer first person shooter Cube. Cube necessitated low latency +communcation with data sent out very frequently, so TCP was an +unsuitable choice due to its high latency and stream orientation. UDP, +however, lacks many sometimes necessary features from TCP such as +reliability, sequencing, unrestricted packet sizes, and connection +management. So UDP by itself was not suitable as a network protocol +either. No suitable freely available networking libraries existed at +the time of ENet's creation to fill this niche. + +UDP and TCP could have been used together in Cube to benefit somewhat +from both of their features, however, the resulting combinations of +protocols still leaves much to be desired. TCP lacks multiple streams +of communication without resorting to opening many sockets and +complicates delineation of packets due to its buffering behavior. UDP +lacks sequencing, connection management, management of bandwidth +resources, and imposes limitations on the size of packets. A +significant investment is required to integrate these two protocols, +and the end result is worse off in features and performance than the +uniform protocol presented by ENet. + +ENet thus attempts to address these issues and provide a single, +uniform protocol layered over UDP to the developer with the best +features of UDP and TCP as well as some useful features neither +provide, with a much cleaner integration than any resulting from a +mixture of UDP and TCP. + +@section CM Connection Management + +ENet provides a simple connection interface over which to communicate +with a foreign host. The liveness of the connection is actively +monitored by pinging the foreign host at frequent intervals, and also +monitors the network conditions from the local host to the foreign +host such as the mean round trip time and packet loss in this fashion. + +@section Sequencing Sequencing + +Rather than a single byte stream that complicates the delineation of +packets, ENet presents connections as multiple, properly sequenced +packet streams that simplify the transfer of various types of data. + +ENet provides sequencing for all packets by assigning to each sent +packet a sequence number that is incremented as packets are sent. ENet +guarentees that no packet with a higher sequence number will be +delivered before a packet with a lower sequence number, thus ensuring +packets are delivered exactly in the order they are sent. + +For unreliable packets, ENet will simply discard the lower sequence +number packet if a packet with a higher sequence number has already +been delivered. This allows the packets to be dispatched immediately +as they arrive, and reduce latency of unreliable packets to an +absolute minimum. For reliable packets, if a higher sequence number +packet arrives, but the preceding packets in the sequence have not yet +arrived, ENet will stall delivery of the higher sequence number +packets until its predecessors have arrived. + +@section Channels Channels + +Since ENet will stall delivery of reliable packets to ensure proper +sequencing, and consequently any packets of higher sequence number +whether reliable or unreliable, in the event the reliable packet's +predecessors have not yet arrived, this can introduce latency into the +delivery of other packets which may not need to be as strictly ordered +with respect to the packet that stalled their delivery. + +To combat this latency and reduce the ordering restrictions on +packets, ENet provides multiple channels of communication over a given +connection. Each channel is independently sequenced, and so the +delivery status of a packet in one channel will not stall the delivery +of other packets in another channel. + +@section Reliability Reliability + +ENet provides optional reliability of packet delivery by ensuring the +foreign host acknowledges receipt of all reliable packets. ENet will +attempt to resend the packet up to a reasonable amount of times, if no +acknowledgement of the packet's receipt happens within a specified +timeout. Retry timeouts are progressive and become more lenient with +every failed attempt to allow for temporary turbulence in network +conditions. + +@section FaR Fragmentation and Reassembly + +ENet will send and deliver packets regardless of size. Large packets +are fragmented into many smaller packets of suitable size, and +reassembled on the foreign host to recover the original packet for +delivery. The process is entirely transparent to the developer. + +@section Aggregation Aggregation + +ENet aggregates all protocol commands, including acknowledgements and +packet transfer, into larger protocol packets to ensure the proper +utilization of the connection and to limit the opportunities for +packet loss that might otherwise result in further delivery latency. + +@section Adaptability Adaptability + +ENet provides an in-flight data window for reliable packets to ensure +connections are not overwhelmed by volumes of packets. It also +provides a static bandwidth allocation mechanism to ensure the total +volume of packets sent and received to a host don't exceed the host's +capabilities. Further, ENet also provides a dynamic throttle that +responds to deviations from normal network connections to rectify +various types of network congestion by further limiting the volume of +packets sent. + +@section Portability Portability + +ENet works on Windows and any other Unix or Unix-like platform +providing a BSD sockets interface. The library has a small and stable +code base that can easily be extended to support other platforms and +integrates easily. ENet makes no assumptions about the underlying +platform's endianess or word size. + +@section Freedom Freedom + +ENet demands no royalties and doesn't carry a viral license that would +restrict you in how you might use it in your programs. ENet is +licensed under a short-and-sweet MIT-style license, which gives you +the freedom to do anything you want with it (well, almost anything). + +*/ + diff --git a/docs/install.dox b/docs/install.dox new file mode 100755 index 0000000..2f0ae1b --- /dev/null +++ b/docs/install.dox @@ -0,0 +1,37 @@ +/** +@page Installation Installation + +ENet should be trivially simple to integrate with most applications. +First, make sure you download the latest source distribution here @ref +SourceDistro. + +@section Unix Unix-like Operating Systems + +[to be completed] + +@subsection SolarisBSD Solaris and BSD + +When building ENet under Solaris, you must specify the -lsocket and +-lnsl parameters to your compiler to ensure that the sockets library +is linked in. + +@section Windows Microsoft Windows + +Using MSVC 6 under Windows simply drag all the ENet source files into +your main project or, better yet, create a new static library project +and make your executable dependent (Project|Dependencies) on ENet. +There is also an enet.dsp provided. + +You will have to link to the Winsock2 libraries, so make sure to add +ws2_32.lib to your library list (Project Settings | Link | +Object/library modules). + +@subsection DLL DLL + +If you wish to build ENet as a DLL you must first define ENET_DLL +within the project (Project Settings | C/C++ | Preprocessor | +Preprocessor definitions) or, more invasively, simply define ENET_DLL +at the top of enet.h. + +*/ + diff --git a/docs/license.dox b/docs/license.dox new file mode 100755 index 0000000..a72c6ea --- /dev/null +++ b/docs/license.dox @@ -0,0 +1,26 @@ +/** + @page License License + +Copyright (c) 2002 Lee Salzman + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + diff --git a/docs/mainpage.dox b/docs/mainpage.dox new file mode 100755 index 0000000..bc4d3a9 --- /dev/null +++ b/docs/mainpage.dox @@ -0,0 +1,84 @@ +/** @mainpage enet + <center>http://enet.cubik.org</center> + <hr> + +ENet's purpose is to provide a relatively thin, simple and robust +network communication layer on top of UDP (User Datagram Protocol). +The primary feature it provides is optional reliable, in-order +delivery of packets. + +ENet is NOT intended to be a general purpose high level networking +library that handles authentication, lobbying, server discovery, +compression, encryption and other high level, often application level +or dependent tasks. + +@ref Features + +@ref SourceDistro + +@ref Installation + +@ref Tutorial + +@ref MailingList + +@ref Extending + +@ref FAQ + +@ref License + + */ + +/** +@page SourceDistro Source Distribution + +You can retrieve the source to ENet by downloading it in either .zip +form, .tar.gz form, or accessing the cvs distribution directly. + +The most recent CVS can be downloaded <a href="http://enet.cubik.org/download/enet.tar.gz">here</a> + +To access ENet via anonymous CVS, you must use the CVSROOT +:pserver:anoncvs\@sferik.cubik.org:/home/enet/cvsroot with an empty +password. + +@code + $ cvs -z3 -d :pserver:[email protected]:/home/enet/cvsroot login +@endcode + Hit the return key when prompted for a password. +@code + $ cvs -z3 -d :pserver:[email protected]:/home/enet/cvsroot co -l . + $ cvs -z3 co enet +@endcode + +This will create a CVS directory in the current directory, and with +the second command will proceed to check the enet module out of CVS. +Any problems with CVS access or request for write access should be +sent via email to @ref MailingList. + +*/ + +/** +@page Extending Extending and Modifying ENet + +Since ENet is distributed in source form, you can easily extend and +modify it to suit your needs. For example, some users prefer to use +their own memory management routines and can thus replace the +appropriate functions in memory.c + +*/ + +/** +@page MailingList ENet Related Mailing Lists + +The <a +href="http://lists.cubik.org/mailman/listinfo/enet-discuss"> +enet-discuss</a> list is for discussion of ENet, including bug reports +or feature requests. + +The CVS commits are also sent to <a +href="http://lists.cubik.org/mailman/listinfo/enet-cvs">enet-cvs</a>, +so feel free to subscribe if you want to keep up with the latest +developments. + +*/ diff --git a/docs/tutorial.dox b/docs/tutorial.dox new file mode 100755 index 0000000..806ca9a --- /dev/null +++ b/docs/tutorial.dox @@ -0,0 +1,349 @@ +/** +@page Tutorial Tutorial + +@ref Initialization + +@ref CreateServer + +@ref CreateClient + +@ref ManageHost + +@ref SendingPacket + +@ref Disconnecting + +@ref Connecting + +@section Initialization Initialization + +Before using ENet, you must call enet_initialize() to initialize the +library. Upon program exit, you should call enet_deinitialize() so +that the library may clean up any used resources. + +@code +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); + ... + ... + ... +} +@endcode + +@section CreateServer Creating an ENet server + +Servers in ENet are constructed with enet_host_create(). You must +specify an address on which to receive data and new connections, as +well as the maximum allowable numbers of connected peers. You may +optionally specify the incoming and outgoing bandwidth of the server +in bytes per second so that ENet may try to statically manage +bandwidth resources among connected peers in addition to its dynamic +throttling algorithm; specifying 0 for these two options will cause +ENet to rely entirely upon its dynamic throttling algorithm to manage +bandwidth. + +When done with a host, the host may be destroyed with +enet_host_destroy(). All connected peers to the host will be reset, +and the resources used by the host will be freed. + +@code + 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 */, + 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); +@endcode + +@section CreateClient Creating an ENet client + +Clients in ENet are similarly constructed with enet_host_create() when +no address is specified to bind the host to. Bandwidth may be +specified for the client host as in the above example. The peer count +controls the maximum number of connections to other server hosts that +may be simultaneously open. + +@code + ENetHost * client; + + client = enet_host_create (NULL /* create a client host */, + 1 /* only allow 1 outgoing connection */, + 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); +@endcode + +@section ManageHost Managing an ENet host + +ENet uses a polled event model to notify the programmer of significant +events. ENet hosts are polled for events with enet_host_service(), +where an optional timeout value in milliseconds may be specified to +control how long ENet will poll; if a timeout of 0 is specified, +enet_host_service() will return immediately if there are no events to +dispatch. enet_host_service() will return 1 if an event was dispatched +within the specified timeout. + +Currently there are only four types of significant events in ENet: + +An event of type ENET_EVENT_TYPE_NONE is returned if no event occurred +within the specified time limit. enet_host_service() will return 0 +with this event. + +An event of type ENET_EVENT_TYPE_CONNECT is returned when either a new client +host has connected to the server host or when an attempt to establish a +connection with a foreign host has succeeded. Only the "peer" field of the +event structure is valid for this event and contains the newly connected peer. + +An event of type ENET_EVENT_TYPE_RECEIVE is returned when a packet is received +from a connected peer. The "peer" field contains the peer the packet was +received from, "channelID" is the channel on which the packet was sent, and +"packet" is the packet that was sent. The packet contained in the "packet" +field must be destroyed with enet_packet_destroy() when you are done +inspecting its contents. + +An event of type ENET_EVENT_TYPE_DISCONNECT is returned when a connected peer +has either explicitly disconnected or timed out. Only the "peer" field of the +event structure is valid for this event and contains the peer that +disconnected. Only the "data" field of the peer is still valid on a +disconnect event and must be explicitly reset. + +@code + ENetEvent event; + + /* Wait up to 1000 milliseconds for an event. */ + while (enet_host_service (client, & event, 1000) > 0) + { + switch (event.type) + { + case ENET_EVENT_TYPE_CONNECT: + 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; + + case ENET_EVENT_TYPE_RECEIVE: + 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. */ + enet_packet_destroy (event.packet); + + break; + + case ENET_EVENT_TYPE_DISCONNECT: + printf ("%s disconected.\n", event.peer -> data); + + /* Reset the peer's client information. */ + + event.peer -> data = NULL; + } + } + ... + ... + ... +@endcode + +@section SendingPacket Sending a packet to an ENet peer + +Packets in ENet are created with enet_packet_create(), where the size +of the packet must be specified. Optionally, initial data may be +specified to copy into the packet. + +Certain flags may also be supplied to enet_packet_create() to control +various packet features: + +ENET_PACKET_FLAG_RELIABLE specifies that the packet must use reliable +delivery. A reliable packet is guarenteed to be delivered, and a +number of retry attempts will be made until an acknowledgement is +received from the foreign host the packet is sent to. If a certain +number of retry attempts is reached without any acknowledgement, ENet +will assume the peer has disconnected and forcefully reset the +connection. If this flag is not specified, the packet is assumed an +unreliable packet, and no retry attempts will be made nor +acknowledgements generated. + +A packet may be resized (extended or truncated) with +enet_packet_resize(). + +A packet is sent to a foreign host with +enet_peer_send(). enet_peer_send() accepts a channel id over which to +send the packet to a given peer. Once the packet is handed over to +ENet with enet_peer_send(), ENet will handle its deallocation and +enet_packet_destroy() should not be used upon it. + +One may also use enet_host_broadcast() to send a packet to all +connected peers on a given host over a specified channel id, as with +enet_peer_send(). + +Queued packets will be sent on a call to enet_host_service(). +Alternatively, enet_host_flush() will send out queued packets without +dispatching any events. + +@code + /* Create a reliable packet of size 7 containing "packet\0" */ + ENetPacket * packet = enet_packet_create ("packet", + strlen ("packet") + 1, + ENET_PACKET_FLAG_RELIABLE); + + /* 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 3. */ + /* One could also broadcast the packet by */ + /* enet_host_broadcast (host, 3, packet); */ + enet_peer_send (peer, 3, packet); + ... + ... + ... + /* One could just use enet_host_service() instead. */ + enet_host_flush (host); +@endcode + +@section Disconnecting Disconnecting an ENet peer + +Peers may be gently disconnected with enet_peer_disconnect(). A +disconnect request will be sent to the foreign host, and ENet will +wait for an acknowledgement from the foreign host before finally +disconnecting. An event of type ENET_EVENT_TYPE_DISCONNECT will be +generated once the disconnection succeeds. Normally timeouts apply to +the disconnect acknowledgement, and so if no acknowledgement is +received after a length of time the peer will be forcefully +disconnected. + +enet_peer_reset() will forcefully disconnect a peer. The foreign host +will get no notification of a disconnect and will time out on the +foreign host. No event is generated. + +@code + ENetEvent event; + + enet_peer_disconnect (& client -> peers [0]); + + /* 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 (& client -> peers [0]); + ... + ... + ... +@endcode + +@section Connecting Connecting to an ENet host + +A connection to a foreign host is initiated with enet_host_connect(). +It accepts the address of a foreign host to connect to, and the number +of channels that should be allocated for communication. If N channels +are allocated for use, their channel ids will be numbered 0 through +N-1. A peer representing the connection attempt is returned, or NULL +if there were no available peers over which to initiate the +connection. When the connection attempt succeeds, an event of type +ENET_EVENT_TYPE_CONNECT will be generated. If the connection attempt +times out or otherwise fails, an event of type +ENET_EVENT_TYPE_DISCONNECT will be generated. + +@code + 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); + + 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 && + event.type == ENET_EVENT_TYPE_CONNECT) + { + 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."); + } + ... + ... + ... +@endcode +*/ |