[Module] Basic TCP/IP suite system in Roblox

I’ve recently been working on a basic roblox module composed of server-side events and got a working client-server networking model. In addition to client-server, it also handles client-client (because the server is actually a client cough).

To clarify, this is NOT talking about the Roblox Server/Roblox Client model. All of this code runs on the server. I’m not sure what to call this module, so for now it’s just “TCP/IP Module”.

Theoretically, it could be used in simulators or house building games where players could communicate via working PCs (a lot of work to implement, but could be a cool idea). I kind of just made this without an actual reason to use it, I just like having it.

Some code examples:

Example client code
local TCPIP = require(TCPIP)
local DeviceIF = TCPIP:CreateDevice(script.Parent, { IP = "10.0.0.2" })

local success = DeviceIF:Connect(path.to.network.switch.part)
if not success then return end

-- Send some data
print("[Client 1]: Connected to switch")
print("[Client 1]: Sending 'hi' to 10.0.0.1 ...")
local success, response = DeviceIF:Send("10.0.0.1", 80, "hi")
if success then
	print("[Client 1] Response from 10.0.0.1:", response)
else
	print("[Client 1 | Error] Response from 10.0.0.1:", response)
end
Example server code
local TCPIP = require(TCPIP)
local DeviceIF = TCPIP:CreateDevice(script.Parent, { IP = "10.0.0.1" })

local success = DeviceIF:Connect(path.to.network.switch.part)
if not success then return end

-- Start listening
print("[Server]: Connected to switch")
DeviceIF:Listen(80, function(ip, data)  -- Listening on the HTTP port because why not?
	print("[Server]:", ip, "sent", data)
	if data == "hi" then
		return true, "hello " .. ip
	elseif data == "bye" then
		return true, "goodbye " .. ip
	else
		return false, "lol wut"
	end
end)
Example switch code
local TCPIP = require(TCPIP)
local SwitchIF = TCPIP:CreateSwitch(script.Parent)

-- Not required, but you can listen to the following:
SwitchIF.DeviceAdded:Connect(function(device)
    print(device)
    wait()
    print("All devices:", SwitchIF.Devices)
end)
SwitchIF.PacketSent:Connect(function(dest, port, data)
    print(dest, port, data)
    -- Currently does not send you "from", coming soon ig
end)
TCP/IP Module
--[[
	TCP/IP Suite written in Luau for Roblox
	No, it's not the *entire* suite, nor does it come close to realistic
	
	Took a damn lot of work though :P
	- iiPythonx
]]

-- Initialization
local function fetchDevice(devs, ip, timeout)
	local d = devs[ip]
	if d then return d end
	wait(timeout)
	return devs[ip]
end

-- Module
local mod = {}
function mod:CreateSwitch(p)
	
	-- Setup events
	local DA = Instance.new("BindableEvent", p)
	local SP = Instance.new("BindableFunction", p)
	DA.Name = "DeviceAdd"
	SP.Name = "SendPacket"
	
	-- Create return object
	local internalSend = Instance.new("BindableEvent")
	local self_ = {
		DeviceAdded = DA.Event,
		PacketSent = internalSend.Event,
		Devices = {}
	}
	DA.Event:Connect(function(d) self_.Devices[d.IP] = d.Host end)
	SP.OnInvoke = function(from, dest, port, data)
		internalSend:Fire(dest, port, data)  -- Just for any extra hooks the switch (may) have
		local dev = fetchDevice(self_.Devices, dest, 1)
		if dev == nil then return false, "device not found" end
		
		-- Send data to device
		local recv = dev:WaitForChild("Receive", 1)
		if recv == nil then return false, "device not initialized" end
		return recv:Invoke(from, port, data)
	end
	return self_
end
function mod:CreateDevice(p, v)
	
	-- Configure IP
	local IP = Instance.new("StringValue", p)
	IP.Name = "IP"
	if v.IP then IP.Value = v.IP end
	
	-- Create return object
	local self_ = {
		SetIP = function(ip) IP.Value = ip end,
		GetIP = function() return IP.Value end,
		ConnectedSendEvt = nil,
		FirewallMap = {}
	}
	function self_:Listen(port, cb) self_.FirewallMap[port] = cb end
	function self_:Connect(dev)
		local DA = dev:WaitForChild("DeviceAdd", 1)
		if DA == nil then return error("Cannot connect to a non-switch device!") end
		DA:Fire({ IP = IP.Value, Host = p })
		self_.ConnectedSendEvt = dev:WaitForChild("SendPacket")
		return true
	end
	function self_:Send(dest, port, data)
		if self_.ConnectedSendEvt == nil then return false, "not connected" end
		return self_.ConnectedSendEvt:Invoke(IP.Value, dest, port, data)
	end
	
	-- Handle receiving data
	local RC = Instance.new("BindableFunction", p)
	RC.Name = "Receive"
	RC.OnInvoke = function(ip, port, data)
		local cb = self_.FirewallMap[port]
		if not cb then return false, "port not open" end
		return cb(ip, data)
	end
	return self_
end
return mod
API Reference
TCPIP:CreateSwitch(part)
Initializes a network switch with the required events and functions.
Attributes:
    - Switch.DeviceAdded: BindableEvent
        callback(device: Table{ IP = "0.0.0.0", Host = part })
    - Switch.PacketSent: BindableEvent
        callback(dest: String, port: Integer, data: Any)
    - Switch.Devices: Table
        { IP: PART, ... }
TCPIP:CreateDevice(part, values)
Initializes a networked device with default values provided
Available values:
    - IP (string): the IP to use; can be set later manually with Device:SetIP(ip)
Attributes:
    - Device:SetIP(ip: String) -> nil
    - Device:GetIP() -> String
    - Device.FirewallMap: Table
        { PORT: Function(ip, data), ... }
    - (private) Device.ConnectedSendEvt

PLEASE NOTE: In order for any connectivity at all, clients have to be connected to a network switch. Is it realistic? No, but this is still the very first “version” of this module that I’ve worked on.

Feel free to give it a shot:
TCP IP Testing.rbxl (37.7 KB)

Gladly open to suggestions.

2 Likes

This is pretty cool! You could potentially design a game that demonstrates how network systems operate, or as a space enthusiast, simulate the deep-space network or Starlink.

It would be interesting if Roblox Staff incorporated TCP/IP sockets within games to provide additional API capabilities outside of the Roblox network or possibly outsource heavy-loaded scripting tasks to a dedicated machine configured by game developer(s).

Thanks for checking it out! I also personally think Roblox should incorporate raw TCP/IP sockets; as I think it could open another world’s worth of possibilities to the platform. I mean imagine the kind of things you could build with direct socket access as if you were a normal program.