Skip to content
Li, Xizhi edited this page Jan 26, 2018 · 9 revisions

NPL TCP Server

One can send or receive any custom messages on a NPL TCP connection. This is usually when the NPL client needs to communicate with a server with custom TCP protocol like google protocol buffer. Or one wants to write a server that is able to handle requests in custom TCP protocol rather than the default NPL protocol. Please note, the default NPL protocol is always recommended when communicating between two NPL nodes. We can dynamically switch between three protocols on the same TCP connections, namely NPL, WebSocket and custom TCP. This section is mainly about writing custom TCP client/server applications.

How To Switch To Custom TCP Protocol

  • If client sends a message to file "tcp", the connection is automatically switched to custom TCP protocol.
  • If server received a message that begins with a char in [0,128-255], the connection is automatically switched to custom TCP protocol if and only if it has a tcp handler file that mapped to id -30, like below.
-- -30 is a predefined file id for web socket. this is needed on both client and server
NPL.AddPublicFile("script/test/network/tcp_client.lua", -30);
  • At any time, a connection can be turned into a custom message manually as below.
-- Change protocol type to 2 (TCP custom) protocol. default 0 is npl protocol.
NPL.SetProtocol(user_id,2);

Writing Custom TCP server

  • Registering a npl file to receive custom TCP message
-- -30 is a predefined file id for web socket. this is needed on both client and server
NPL.AddPublicFile("script/test/network/tcp_server.lua", -30);
-- a server that listen on 8099 for all IP addresses
NPL.StartNetServer("0.0.0.0", "8099");
  • Receiving message
--script/test/network/tcp_server.lua
local function activate()
    local user_id = msg.tid or msg.nid;
    local binary_data = msg[1];
    echo("partial data received:"..binary_data);
    if(math.random() < 0.5) then
        -- this is how server can send a message back to client
        NPL.activate(format("%s:tcp", user_id), "replied"..binary_data);
    end
end
NPL.this(activate)

Please note message received is unparsed partial data, one needs to parse and handle parsed messages in real applications. Parsing raw binary stream in NPL main handler thread is less optimum in performance, it is recommended to use NPL default protocol when possible.

Writing Custom TCP Client

-- this only needs to called once to name a remote TCP server
-- -30 is a predefined file id for web socket. this is needed on both client and server
NPL.AddPublicFile("script/test/network/tcp_client.lua", -30);
NPL.StartNetServer("0.0.0.0", "0");
local server_nid = "myserver01";
NPL.AddNPLRuntimeAddress({host="127.0.0.1", port="8099", nid=server_nid})
	

local server_addr = string.format("%s:tcp",server_nid);

-- connect with 2 seconds timeout
-- if the first message begins with \0 or non-char character, we will automatically use a custom TCP connection
if(NPL.activate_with_timeout(2, server_addr, "\0first_binary_message") == 0) then
	-- now let us send some arbitrary binary message
	for i=1,10 do
		NPL.activate(server_addr, "i=\0"..i);
	end
end
  • Receiving message
--script/test/network/tcp_client.lua
local function activate()
    local user_id = msg.tid or msg.nid;
    local binary_data = msg[1];
    echo("partial data received:"..binary_data);
end
NPL.this(activate)

Example: A simple echo server/client

Both client and server share the same file.

--[[
Author: LiXizhi@yeah.net
Date: 2018-1-25
Desc: testing tcp server
-----------------------------------------------
-- to test, run following code
NPL.load("(gl)script/test/network/tcp_server.lua");
test_tcp_server();
test_tcp_client();
-----------------------------------------------
]]
NPL.load("(gl)script/ide/commonlib.lua"); -- many sub dependency included


function test_tcp_server(input)
	-- -30 is a predefined file id for web socket. this is needed on both client and server
	NPL.AddPublicFile("script/test/network/tcp_server.lua", -30);
	-- a server that listen on 8099 for all IP addresses
	NPL.StartNetServer("0.0.0.0", "8099");
end

function test_tcp_client()
	-- this only needs to called once to name a remote TCP server
	-- -30 is a predefined file id for web socket. this is needed on both client and server
	NPL.AddPublicFile("script/test/network/tcp_server.lua", -30);
	NPL.StartNetServer("0.0.0.0", "0");
	local server_nid = "myserver01";
	NPL.AddNPLRuntimeAddress({host = "127.0.0.1", port = "8099", nid = server_nid})
	

	local server_addr = string.format("%s:tcp", server_nid);

	-- connect with 2 seconds timeout
	-- if the first message begins with \0 or non-char character, we will automatically use a custom TCP connection
	if(NPL.activate_with_timeout(2, server_addr, "\0first_binary_message") == 0) then
		-- now let us send some arbitrary binary message
		for i = 1, 10 do
			NPL.activate(server_addr, "i=\0"..i);
		end
	end
end


local function activate()
	local user_id = msg.tid or msg.nid;
	local binary_data = msg[1];
	echo("partial data received:"..binary_data);
	if(math.random() < 0.5) then
		-- this is how server can send a message back to client
		NPL.activate(format("%s:tcp", user_id), "replied"..binary_data);
	end
end
NPL.this(activate)

Example: A google protocolbuffer client/server

TODO: for leio

Clone this wiki locally