Need an efficient binary networking example for server & clients.

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.
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Need an efficient binary networking example for server & clients.

Post by zorg »

First, i do want to apologize for my tone earlier, the whole thread feels/felt like a massive miscommunication, to put it mildly, so i was a bit aggravated.

Still, let me try to summize as concisely as i can, and let me give you an example of what i meant by using unions.
BorhilIan wrote: Sun Mar 19, 2017 4:15 am

Code: Select all

net.Begin( "UpdatePlayer" ) - Converted to a numeric header for the packet and starts my packet assembler. (This method will allow custom net packets for modders to use)
	net.Write( 127 , 8 ) -- First is the value to send, Second is the number of bits. (Will be unsigned regardless no negative numbers needed)
net.Send() - Send the packet to the specified targets on server or to server on client and clears the packet assembler.
net.Broadcast() - Send the packet to all clients on the server except for specified. (would be called in place of 'net.Send()')
Second receive the packet.

Code: Select all

net.Receive( "UpdatePlayer" , function()
	local value = net.Read( 8 ) -- Read the first eight bits which would return the 127 value.
end )
Thirdly this basic networking system will enable me to do the following.

Code: Select all

net.WriteString = function( txt )
	net.Write( string.len( txt ) , 8 ) -- Send the length of the string up to 255 characters.
	for k , c in pairs( txt ) do
		net.write( string.byte( c ) , 8 ) -- Here would be a converter to binary from string.
	end
end
net.ReadString = function()
	local len = net.Read( 8 ) -- Read the length of the string from the first byte.
	local txt = {}
	for i = 1 , len do
		txt[ i ] = string.char( net.Read( 8 ) )
	end
	return table.concat( txt )
end
In your original post, the two code blocks to me don't really correlate; The first, to me, seems pretty straightforward; a numeric header (sent as binary, hopefully as a full 8-bit-aligned packet) followed by data fitting in the specified bit lengths; now, if the header is uniform in length, you don't need to transmit the packet type's internal structure (i.e. the bit layout) since that exists on all sides, and based on the header received, the correct code will read in the correct amount of data and recombine it into the values you sent; perfectly clear.

Still, no computer or programming language handles anything on the level of individual bits; yes, you can do uneven-bit-fields and the like, especially with C structs, but it will need to be padded to byte-boundaries too, which you yourself acknowledge; how it looks internally / how it's handled internally is inconsequential.
BorhilIan wrote: Mon Mar 20, 2017 4:35 am Sorry i'm not very good at explaining things. The issues with networking data in cast strings is each character in that string is 1 byte. So lets say I just wanted to send a value which ranges from 0 - 16 (4 bits) I would effectively cast that to 1 byte (8 bits) if using strings to network data. Which would not be ideal for my desired application which involves lots of varidable range values being transferred.
As was said before, there are methods to pack variable bit-width values into 8-bit arrays. On the outside, it's still handled as an array, whether of bytes or chars, signed or unsigned.
BorhilIan wrote: Mon Mar 27, 2017 12:54 am Just need two functions for converting a number to/from binary.
This will indeed be my code example.

Code: Select all

local ffi = require("ffi")
ffi.cdef[[
typedef union {
  double d;
  char bytes[sizeof(double)];
} numbin;
]]
local magic = ffi.new("numbin", {})
magic.d = 53.34 -- lua number, which is a double, gets assigned to magic as a double.
print(ffi.string(magic.bytes, 8)) -- the same variable, magic, gets printed as 8 bytes, the width of a double.
This is a way to get the underlying binary representation of some type; namely, lua numbers (with standard settings as used by Löve).
Though luaJIT states that "Packed struct bitfields that cross container boundaries are not implemented." that doesn't mean that bitfields within container boundaries aren't; i haven't tested it myself, but basically, it would mean the following:

Code: Select all

local ffi = require("ffi")

-- The below struct would work, since 4+1+3 bits == 8 bits, which is the width of the char type.
ffi.cdef[[
typedef union {
  struct {
  	char fourbit : 4;
  	char onebit : 1;
  	char threebit : 3;
  } combined;
  char bytes[sizeof(char)];
} numbin;
]]

-- The below goes over the underlying datatype's length boundary (here, uint_32_t) by one bit, so it'll probably error...
ffi.cdef[[
typedef union {
  struct {
  	uint32_t a : 15;
  	uint32_t b : 7;
  	uint32_t c : 11;
  } combined;
  char bytes[sizeof(uint32_t)];
} numbin;
]]

I'm assuming that as long as one stays between the boundaries, then even a more complex struct could be defined with multiple data types... but sadly i'm not at home so i can't test this out myself. (and yes, my code may have bugs in it, apologies for that.)
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.
BorhilIan
Prole
Posts: 38
Joined: Wed Mar 15, 2017 6:46 am

Re: Need an efficient binary networking example for server & clients.

Post by BorhilIan »

Thanks for the rather clear reply, this thread was a train-wreck. I have everything figured out and don't need further assistance. Expect me to post the result in the 'Libraries and Tools' forum within the week. I'm currently making a basic interactive '.love' demo which will display text in the window for others to play with. It will allow a user to input basic numbers and cast them to/from binary. Write/Read the values to/from a visual buffer and hopefully in general be very informative and useful. (It wont use any networking, it will purely be for demoing the buffer system I intend to use, which I can hopefully improve through feedback)

EDIT: Yeah that cdef stuff escapes me though I don't see any possible use for my project, I know C# (very well) and very little c++ as well as java, ruby (mostly just syntax) and a few others I've rarely touched.
BorhilIan
Prole
Posts: 38
Joined: Wed Mar 15, 2017 6:46 am

Re: Need an efficient binary networking example for server & clients.

Post by BorhilIan »

Just posted a Tool/Demo which showcases what I was trying to do and how I've done it, specifically the 'tobinary( number , bits )' and 'tonumber( binary , 2 )' functions. So if you read this thread looking for the same go to [Tool/Example] Write/Read to binary Buffer.
Post Reply

Who is online

Users browsing this forum: No registered users and 86 guests