Questions about sockets and checking for recieved data


#1

So I am working on a solo project for fun. I essentially made a socket server in c# and can send data to it with the lua client created in defold.
I was just wondering how I can check for received data in defold from the server.
So say I send a string to the client from the server how would I check for any data or specific data sent from the server.
so something like
if(client:recievedData)then
print(recievedData)
end
also was wondering how I can check if the client got connected in lua.
I have looked over the lua socket api but can’t find it.
Is there such a function for this?

any help would be greatly appreciated <3


#2

It’s non trivial to make non-blocking socket connections. You can take a look at the tcp client in DefNet for inspiration (https://github.com/britzl/defnet/blob/master/defnet/tcp_client.lua).

socket.select() takes two lists of sockets to check for ability to read and write from.

The receive() function on a client socket is used to read data (possibly partial data).


#3

Sorry but I see receive has two arguments how would I go about receiving any data coming in?
say I send a hi from the server.
how would I print the hi in the console on defold engine?

so something line

if client:receive() then
 print(client:msg)
end

Sorry I know this may be a nooby question but I really do need help on this. I just don’t understand it yet.


#4

The documentation (https://www.defold.com/ref/socket/#client:receive:-pattern---prefix-) says the two arguments are pattern and prefix.

Pattern is either a number with the number of bytes you wish to read or a string indicating how to read data, “*l” reads until a newline for instance. Prefix is any already read data to prefix received data with.


#5

is there a way to set pattern as whatever bytes are received?


#6

Again, the documentation (https://www.defold.com/ref/socket/#client:receive:-pattern---prefix-):

“*a” reads from the socket until the connection is closed. No end-of-line translation is performed;


#7

ok thanx Ill give it my best shot :slight_smile:

wow I feel kinda dumb now ;(
I figured the “*a” was something I was suppose to specify myself not just write “*a”
yup I’m dumb


#8

You will likely not want to use “*a”. It will read until there are no more bytes. I’m not sure what would happen if there’s like a megabyte of data to receive but it will likely cause a hitch while receiving. It’s better, in a game, to set timeout to 0 and read in chunks. Especially if you don’t know how much data there is.


#9

just a question sorry still having trouble showing the data from the receive
if I wanted to show the received data could I in theory do

local data = client:receive("*a", 0)
if data then
         print(data)
end

reason I ask is because I am just trying to make sure I have my client setup right so I can troubleshoot if I am sending the data correctly or not from the server.
sorry again.


#10

bump


#11

What kind of problem? Are you not receiving any data?

I think it’s better if you share all of your socket handler code. It’s hard to tell if what you’re doing is good or bad.

Did you look at the tcp_client.lua from DefNet? It handles non-blocking TCP socket clients without any problems. Sending and receiving data.


#12

I did have a look at it but for some reason it will not connect to my server, not sure why. it doesn’t give an error just says connection was denied.
anyways here is my current code for what I have in my login script . it works completely I just don’t know how I can check for the data I send back.

local tcp_client = require "main.scripts.tcp_client"
local IP = "localhost"
local PORT = 5392

function init(self)
	sock = socket.connect(IP, PORT)
	self.user_message = ""
	self.pass_message = ""
	msg.post(".", "acquire_input_focus") 
	self.message = "" 
	status = gui.get_node("Status")
	
	if not sock then
		gui.set_text(status, "server offline")
	end
	if sock then
		gui.set_text(status, "server online")
	end
	
end
function onData(data)
	print(data)
end
function onDisconnect()
	print("disconnected")
end
function on_input(self, action_id, action)
	local userField = gui.get_node("userBg")
	local passField = gui.get_node("passBg")
	local loginBtn = gui.get_node("loginBtn")
	if(gui.pick_node(userField, action.x, action.y))then
		self.field_selected = "user"
		userField = gui.get_node("userField")
		userTxt = gui.get_text(userField)
	end
	if(gui.pick_node(passField, action.x, action.y))then
		self.field_selected = "pass"
		passField = gui.get_node("passField")
		passTxt = gui.get_text(passField)
	end

	if(gui.pick_node(loginBtn, action.x, action.y))then
		sock:send(self.user_message .. "," .. self.pass_message)
		
	end
	if self.field_selected == "user" then
		if action_id == hash("type") then
			self.user_message = self.user_message .. action.text
			gui.set_text(userField, self.user_message) 
		elseif action_id == hash("backspace") and action.repeated then
			local l = string.len(self.user_message)
			self.user_message = string.sub(self.user_message, 0, l-1) 
			gui.set_text(userField, self.user_message)
		end
	end
	if self.field_selected == "pass" then
		if action_id == hash("type") then
			self.pass_message = self.pass_message .. action.text
			gui.set_text(passField, self.pass_message)
		elseif action_id == hash("backspace") and action.repeated then
				local l = string.len(self.pass_message)
				self.pass_message = string.sub(self.pass_message, 0, l-1) 
				gui.set_text(passField, self.pass_message)
			
		end
	end
end

would really appreciate any help I can get


#13

You don’t have any place where you try to receive data on the socket. All I see is the sock:send() call when clicking the login button. Why do you use sockets for that by the way? It would make a lot more sense to do a login using a normal HTTP request.

Anyway, if you want to receive data on the socket you need to poll for it with some interval. To check if you can read from the socket you use socket.select(). A good place to do this would be in an update loop or using a repeating timer:

-- check if it's possible to read from the socket
-- 0 = don't block the thread, wait 0 seconds
local receivet,sendt = socket.select({ sock }, nil, 0)
-- if the socket is in receivt then it means it's possible to read from the socket
if receivet[sock] then
    -- read a line from the socket (ie until a linebreak \n)
    -- err can be "closed" or "timeout"
    local data, err = sock:receive("*l")
    print("received", data, err)
end