Luasocket - problem with any serialized data (SOLVED)

So I’m using TCP and UDB with Lua sockets.
With TCP as I want to send “packages” in varied serialized sizes I’m using “*l” as a pattern when recieving the data.

Problem is that whenever a byte (or string char if you like) happens to have the number 10 (or 13) the package breaks as it is the linefeed char that “ends” the package. So whenever I am unfortunate to have a serialized data that contains a byte of 10 the package gets totally broken.

I have been trying to use “*a” but it doesnt seem to work. This never gets anything.

    -- RECEIVE
    	local data, err = con.tcp_client:receive("*a")
    	while data do
    		con:unpack_packet(data)
    		data, err = con.tcp_client:receive("*a")
    	end

I haven’t been able to find a solution to this yet. Any suggestions?

You probably need to rethink how you send your packages. Why not start by sending the length of the package and do something like:

local length = con.tcp_client:receive(4)
local package = con.tcp_client:receive(length)

You do need to add some code to deal with when not all of the data is available and in that case continue to poll the socket for the rest of the data. How do you package your data? Are you using Trickle or something similar?

1 Like

I think this reads data until the remote end disconnects.

Hi Britzl and thanks. I tried length previously and for some reason I couldnt make it happen. I guess I’ll have to look at it again.
Yes I have wrapped Trickle with some other features like signed values, quantize values (for floats) and bundled messages.

I’ll post when I find a solution (or get totally stuck)

1 Like

Fixed it and it works like a charm. Thank you!

For future reference and if someone is interested, the solution for receiving server side (several clients/connections) became this (connection or con is a table with all data for that connection).

-- RECEIVE
	local read, _, err = socket.select(connections.clients, nil, 0)
	for _,client in ipairs(read) do
		local con = connections.connections_by_client[client]
		coroutine.wrap(function()
			local retry = true
			while retry == true do
				retry = false
				if con.packet_len then 
					local data, err, part = con.tcp_client:receive(con.packet_len)
					if data then
						con:unpack_packet(data)
						con:reset_package_length()
						retry = true
					elseif err and err == "closed" then
						print("Client connection closed", client)
						connections.disconnect(client)
					end
				else
					local data, err, part = con.tcp_client:receive(2)
					if data then
						con:set_package_length(data)
						retry = true
					elseif err and err == "closed" then
						print("Client connection closed", client)
						connections.disconnect(client)
					end
				end
			end
		end)()
6 Likes