The code shows off a simple implementation using ENet of a chat using the client-server architecture model. This code doesn't show off multithreaded to keep the focus simple and on enet. You can learn more about multithreading from love's wiki.
The code includes comments - but this document goes into a more high level overview of the code.
You can run either of the bat files or the shell scripts provided. Run the server before starting any clients. Otherwise you can run any of the main.lua
within their self-containing folders.
main.lua
on the top level is used as a basic switch between client and server to have a single entry point for the code base. Using the argument -server
, see the bat or shell files to see this in action.
NOTE, this code can be access through the network (E.g. LAN/WAN (web)) if port 12345
is open. You can change this behaviour to run only on localhost if you change the address variable within the server's main.lua
to localhost
or 127.0.0.1
from the original value of *
The server is where the magic of networking starts. First with ENet you must create a host.
local host = enet.host_create(address..":"..port)
The above is how the address shall be formatted. The address can be of 4 values.
*
or 0.0.0.0
allows the server to run open to the network
localhost
or 127.0.0.1
allows the server to only run on the machine - not accessible from outside that machine. (Do note that localhost's value can be changed on the machine - by default it will direct to 127.0.0.1)
Now that you've created the host, you need to start the server. To start the server you need to run the :service()
function. If the server starts it will return an event, otherwise it will not return an event. This usually means the port has been taken by another program - and ports cannot be shared.
Lastly we get to the main loop of the server.
local event = host:service(50) -- 50ms timeout
while event do
log("Event received. Type: "..event.type..", from:"..tostring(event.client).." containing: "..tostring(event.data))
event = host:check_events() -- get next event in queue
end -- will exit once the event queue has been emptied
There are 3 types of events, the table below contains what variables are available and their type. You can learn more from love own wiki.
event.type | event.peer | event.data |
---|---|---|
"receive" | peer | string |
"disconnect" | peer | number |
"connect" | peer | number |
Messages are sent between server to client using peer objects that can be found within events from the event.peer
variable. Peers have many more functions that you access that can be read about on love's wiki. NOTE, to find a peer's connected ip and port you have to use tostring(peer)
- it isn't documented on love's wiki.
The client contains about the same amount of code as the server does - it has a few extra functions to capture and send messages however.
It works almost the same as the server, except it doesn't ask for a variable when creating the host - and requires you to call the connect function on the host. Similarly, it doesn't connect to the server until :service()
is called
local host = enet.host_create()
local server = host:connect(address..":"..port) -- server is peer object
local event = host:service(5000) -- connection messages sent here
Do note that the address to the server will depend which network it is on compared to the client machine. If running on the same machine then localhost
will work even if the server uses either *
or 0.0.0.0
. If the machine is connected on the a different router then you would need to use the public IP, and have port forwarding(NAT) involved on the server's router. If you're running on the same router network then you can use the private IP - but you can use the public IP if the port has been port forwarded (NAT). Sometimes a router is old, and cannot connect to machines within it's own network - then you would need to use public IP with port forwarding. Check out Cannot connect to server if you're having connection issues.
Once the client has connected to the server the network loop is practically the same as the server's. However, to send a message to the server you have to use the server's peer object created when running the connect function.
In the client example you can see the chat program sending the message within the love.keypressed
call-back function when return
is pressed.
If you cannot connect to the machine - but can ping it using the ping command in a terminal using the same ip address. Then usually the issue lies with the client or server's firewall blocking the connection. Ensure that love.exe has access through the firewall (If you fuse your game, then that program must also be let through).
If you're using a private IP that worked one day but doesn't anymore - check that machine still has the same one as router usually refresh the connected devices IPs every 24 hours or so by default.