UDP networking for multiplayer game

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
mxmlnbndsmnn
Prole
Posts: 37
Joined: Mon Feb 11, 2019 4:17 pm

Re: UDP networking for multiplayer game

Post by mxmlnbndsmnn »

Ok :o
I dont really see a walkaround here so I will probably just stick to the less friendly method of having the users input the address manually. At least for now (I dont like giving up ^^).
User avatar
keharriso
Party member
Posts: 103
Joined: Fri Nov 16, 2012 9:34 pm

Re: UDP networking for multiplayer game

Post by keharriso »

I got it working by taking out the "if connected" code and using "0.0.0.0" instead of "*". Check out the attached files.
Attachments
udp-broadcast-example.zip
(2.69 KiB) Downloaded 166 times
LÖVE-Nuklear - a lightweight immediate mode GUI for LÖVE games
mxmlnbndsmnn
Prole
Posts: 37
Joined: Mon Feb 11, 2019 4:17 pm

Re: UDP networking for multiplayer game

Post by mxmlnbndsmnn »

Interesting that this work but the actual broadcast method does not (at least on the systems you mentioned).

Tried it in a LAN and worked :)

Now that the sockname is set to "0.0.0.0", using getsockname() always returns this useless "address". Obviously when using receivefrom and sendto after the first "handshake" has been made, the server knows the IP address from the connected client(s) but not himself (well somehow he must know it ... but getsockname won't help me there). Same thing on the client side. I thought about both server and client sending the address information about their counterpart TO their counterpart and after that killing the connection and then set it up again ... but that sounds stupid tbh ^^

Two more things...

1) You said do not use setpeername at the client. Why? It feels wrong/bad to use sendto instead of "binding" the socket and then simply use send. Should be a slight performance gain, too.

2) What does this

Code: Select all

local a, b = udp:sendto("promo", "255.255.255.255", clientPort)
output on your machine? I am getting 5 and nil.
Why am I asking, you ask? Because the reference says "If successful, the method returns 1. In case of error, the method returns nil followed by an error message." (http://w3.impa.br/~diego/software/luaso ... tml#sendto) Hm ... ? I haven't found any more detailed description of the return values.
User avatar
keharriso
Party member
Posts: 103
Joined: Fri Nov 16, 2012 9:34 pm

Re: UDP networking for multiplayer game

Post by keharriso »

mxmlnbndsmnn wrote: Thu Apr 04, 2019 1:01 pm 1) You said do not use setpeername at the client. Why? It feels wrong/bad to use sendto instead of "binding" the socket and then simply use send. Should be a slight performance gain, too.
This one I honestly don't know the answer to. For some reason, I was getting an error with setpeername. You can try adding it back in now that everything is working.
mxmlnbndsmnn wrote: Thu Apr 04, 2019 1:01 pm 2) What does this

Code: Select all

local a, b = udp:sendto("promo", "255.255.255.255", clientPort)
output on your machine? I am getting 5 and nil.
Why am I asking, you ask? Because the reference says "If successful, the method returns 1. In case of error, the method returns nil followed by an error message." (http://w3.impa.br/~diego/software/luaso ... tml#sendto) Hm ... ? I haven't found any more detailed description of the return values.
It looks like sendto returns the number of bytes sent instead of 1. This is likely an error in the documentation.
LÖVE-Nuklear - a lightweight immediate mode GUI for LÖVE games
User avatar
zorg
Party member
Posts: 3449
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: UDP networking for multiplayer game

Post by zorg »

keharriso wrote: Thu Apr 04, 2019 1:41 pm
mxmlnbndsmnn wrote: Thu Apr 04, 2019 1:01 pm 2) What does this

Code: Select all

local a, b = udp:sendto("promo", "255.255.255.255", clientPort)
output on your machine? I am getting 5 and nil.
Why am I asking, you ask? Because the reference says "If successful, the method returns 1. In case of error, the method returns nil followed by an error message." (http://w3.impa.br/~diego/software/luaso ... tml#sendto) Hm ... ? I haven't found any more detailed description of the return values.
It looks like sendto returns the number of bytes sent instead of 1. This is likely an error in the documentation.
And the string "255.255.255.255" being sent is 5 bytes long? Not seeing any compression done there...
Edit: Wow, i'm more blind than i thought, sorry bout that. :oops:
Last edited by zorg on Thu Apr 04, 2019 6:51 pm, edited 1 time in total.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
keharriso
Party member
Posts: 103
Joined: Fri Nov 16, 2012 9:34 pm

Re: UDP networking for multiplayer game

Post by keharriso »

No, the string being sent is "promo". "255.255.255.255" is the broadcast address.
LÖVE-Nuklear - a lightweight immediate mode GUI for LÖVE games
mxmlnbndsmnn
Prole
Posts: 37
Joined: Mon Feb 11, 2019 4:17 pm

Re: UDP networking for multiplayer game

Post by mxmlnbndsmnn »

Yep, you're right about the byte length (at least it seems so). Sending "promote" instead, returns 7 ... => approved ;)

I figure out the setpeername error: I use receivefrom as long as the client does not know the server. Once the client gets accepted from the server, I can call setpeername and after that I have to use receive - not receivefrom. In general, that's what I'm doing but in real I had to cancel the listening once I call setpeername in one receive cycle:

(unconnected state)

Code: Select all

repeat
	local datagram, msg_or_nil, port_or_nil = udp:receivefrom()
	--print(datagram, msg_or_nil, port_or_nil)
	
	if datagram then
		print("unconnected client received: " .. datagram)
		
		if datagram == "promo" then
			if not self.client.joinRequestPending then
				if udp:sendto("askjoin", msg_or_nil, port_or_nil) then
					self.client.joinRequestPending = true
					self.client.peer = { ip = msg_or_nil, port = port_or_nil }
					print(self.client.peer.ip, self.client.peer.port)
				end
			end
		
		elseif datagram == "acceptjoin" then
			self.client.joinRequestPending = false
			self.client.connected = true
			udp:setpeername(msg_or_nil, port_or_nil)
			
			print("network: client connected to...")
			print(msg_or_nil, port_or_nil)
			
			local _ip, _port = udp:getsockname()
			print("client ip: " .. tostring(_ip) .. " port: " .. tostring(_port))
			break --< this dude was needed
		end
	
	elseif msg_or_nil ~= "timeout" then
		print("client: Network error (2): " .. tostring(msg_or_nil))
	end
until not datagram
User avatar
pgimeno
Party member
Posts: 3593
Joined: Sun Oct 18, 2015 2:58 pm

Re: UDP networking for multiplayer game

Post by pgimeno »

There's a reason why it's not so easy for a server to determine its own IP address: there may be several network interfaces in the machine, each with its own IP, and even one single network interface can have several IP addresses. When the bind address is 0.0.0.0 (all interfaces), which address is used typically depends on the destination address, according to the routing table. For the global broadcast address 255.255.255.255, I guess that all IPs in all interfaces will send the broadcast, probably including localhost, for example. I haven't tested that.

With some luck, you may be able to find a way to retrieve the complete list of IP addresses that a server supports, and let the user hosting the server choose one. If there's only one after discarding 127.x.y.z, you can actually pre-configure it. I haven't found anything in the LuaSocket documentation that deals with interfaces; however it seems that you can use local _, info = socket.dns.toip(socket.dns.gethostname()) to get IP information in info.ip[1], info.ip[2] etc.. This isn't so reliable as querying the IPs of all interfaces, but it might be a start, at least something to fill the server IP entry field with initially.

And that's what I suggest for the server: to offer the user an entry field where to input the server IP, perhaps pre-filled as described above. The idea of having the clients send the server its own IP address sounds pretty insecure to me. The opposite doesn't sound too bad, though a rogue server could use that for DDoSing a machine.

I haven't even touched the possibility of having a machine connected to two local networks, with some clients in one and others in the other. In such a case, the server needs one IP for talking to one set of clients and another for talking to the other set.
User avatar
keharriso
Party member
Posts: 103
Joined: Fri Nov 16, 2012 9:34 pm

Re: UDP networking for multiplayer game

Post by keharriso »

pgimeno wrote: Thu Apr 04, 2019 3:07 pm The idea of having the clients send the server its own IP address sounds pretty insecure to me. The opposite doesn't sound too bad, though a rogue server could use that for DDoSing a machine.
Correct me if I'm wrong, but wouldn't the client and server both know each other's IP addresses simply because they exchange UDP messages? udp:receivefrom is all it takes to find out the other end's IP address. The only way I know to avoid this would be using a VPN and/or proxy.
LÖVE-Nuklear - a lightweight immediate mode GUI for LÖVE games
User avatar
pgimeno
Party member
Posts: 3593
Joined: Sun Oct 18, 2015 2:58 pm

Re: UDP networking for multiplayer game

Post by pgimeno »

Um, yeah, I haven't used UDP that much :oops: (but there's another way, to forge sender addresses)
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 3 guests