After fiddling with luasocket and UDP for a while I moved on to using enet which seems kinda cool.
I got a working server-client connection which I have tested to work fine on two win10 machines in the same WLAN.
However, before actually trying to building a game around this working connection I tested how reliable the message exchange actually is... and here I run into a roadblock that I don't understand.
When I try to send multiple messages right after another, the peer will only receive a fraction of those, even if all messages are send in the default "reliable" mode. Client sends message 1, 2, ..., 5 but the server only receives messages 1,3 and 5 OR sometimes only message 2 and 4 (wtf?).
Yes I know, for i = 1,5 do client:send(...) does not seem practical (I could merge them in this case) but I assume that later I might have multiple things that should be exchanged simultaneously.
I am also aware of the channel functionality, which looks very useful, but this will be the next step on my research plan.
See the attached file. You can configure the server IP in an extra file if you unzip it. For now it is set to "localhost" for testing on the same PC.
Things I already tried:
- decreased the time between updates
- put client.host:service() before a client.server:send
- instead of service() I also tried a timeout of 10 and 100, meaning service(100)
- I explicitly passed "reliable" as argument to the send function, as well as "unreliable" and "unsequenced"
For those of you how just want to take a look at the (mostly) working code without downloading, here is the main file:
(edited, the suggestion from zorg was correct, code should be working now)
Code: Select all
local lg = love.graphics
local enet = require "enet"
local updateRate = 0.1
-- so far, both "*" and "0.0.0.0" seem to work (same PC or WLAN)
-- and ofc "localhost" when running on the same PC
local SERVER_IP = require "server_ip"
local SERVER_PORT = 16666
local MAX_PEER_COUNT = 4
----------------------------------------------------------------------------------------------------
function love.load()
end
----------------------------------------------------------------------------------------------------
function love.update( dt )
if server then
server:tick( dt )
elseif client then
client:tick( dt )
end
end
----------------------------------------------------------------------------------------------------
function love.draw()
if server then
lg.print( "SERVER", 10, 5 )
for i = 1, MAX_PEER_COUNT do
local peer = server.host:get_peer( i )
if peer then
lg.print( string.format( "%d - %s [%d]", i, peer:state(), peer:last_round_trip_time() ), 10, 5 + 10 * i)
end
end
elseif client then
lg.print( "CLIENT", 10, 5 )
lg.print( string.format( "%s [%d]", client.server:state(), client.server:last_round_trip_time() ), 10, 15 )
end
end
----------------------------------------------------------------------------------------------------
local Server = {}
function Server:create()
local server = {}
server.time = 0
server.updateTick = 0
server.host = enet.host_create( string.format( "%s:%d", SERVER_IP, SERVER_PORT) , MAX_PEER_COUNT )
print( "Create server at", server.host:get_socket_address() )
function server:tick( dt )
self.time = self.time + dt
-- update rate
self.updateTick = self.updateTick + dt
if self.updateTick > updateRate then
self.updateTick = 0
self:listen()
end
end
function server:listen()
local event
repeat
event = self.host:service()
if event then
if event.type == "receive" then
print( "received:", event.data )
print( "from", event.peer )
event.peer:send( "((answer))" )
elseif event.type == "connect" then
print( "Client connected", event.peer )
event.peer:send( "hallo, client" )
print( "peer:", event.peer:index() .. "/" .. self.host:peer_count() )
elseif event.type == "disconnect" then
print( "Client disconnected", event.peer )
end
end
until not event
end
return server
end
----------------------------------------------------------------------------------------------------
local Client = {}
function Client:create()
local client = {}
client.time = 0
client.updateTick = 0
client.host = enet.host_create()
client.server = client.host:connect( string.format( "%s:%d", SERVER_IP, SERVER_PORT) )
print( "Create client at", client.host:get_socket_address() )
function client:tick( dt )
self.time = self.time + dt
-- update rate
self.updateTick = self.updateTick + dt
if self.updateTick > updateRate then
self.updateTick = 0
self:listen()
end
end
function client:listen()
local event
repeat
event = self.host:service()
if event then
if event.type == "receive" then
print( "received:", event.data )
print( "from", event.peer )
elseif event.type == "connect" then
print( "Client connected", event.peer )
elseif event.type == "disconnect" then
print( "Client disconnected", event.peer )
end
end
until not event
end
return client
end
----------------------------------------------------------------------------------------------------
function love.keypressed( key, scancode, isrepeat )
if not server and not client then
if key == "s" then
server = Server:create()
elseif key == "c" then
client = Client:create()
end
end
if key == "escape" then
if client then
client.server:disconnect()
client.host:flush()
client.host:destroy()
client = nil
elseif server then
server.host:destroy()
server = nil
end
elseif key == "m" then
if client then
-- client.host:service()
for i = 1,5 do
client.server:send( "hi " .. i )
end
elseif server then
server.host:broadcast( "hello @ all" )
end
end
end