cfadmin - write high-performance server and client instances

Keywords: C network lua

Reading this article requires readers to have at least a basic knowledge of C/C + + network programming and how to use the basic Socket API

At the same time, readers should have at least used cfadmin framework and be proficient in using built-in library to complete simple business logic writing

Students interested in this article can also Official website And file To learn more about how to use the framework

Read the preface

cfadmin is a high-performance server-side framework written by C and Lua. Although the current Web service is built in, it still needs to use the original socket

cfadmin encapsulates most socket APIs. Developers can only use the internally provided Lua interface without considering the C/C + + level

From this chapter, I will learn how to use cfadmin hidden widgets

quick get start

We create script/client.lua and script/server.lua files respectively in the script directory, and write the following contents:

-- script/server.lua
local TCP = require "internal.TCP"

local server = TCP:new()

server:listen("127.0.0.1", 8080, function (fd, ip, port)
  local sock = TCP:new():set_fd(fd)

  print(fd, ip, port)

  sock:close()
end)
-- script/client.lua
local TCP = require "internal.TCP"

local client = TCP:new()

assert(client:connect("127.0.0.1", 8080))

print("Connection succeeded.")

client:close()

Then, we open two terminals to run them:

root@server:~/cfadmin$ ./cfadmin -e script/server.lua
8       ::ffff:127.0.0.1        15504
root@server:~/cfadmin$ ./cfadmin -e script/client.lua
 Connection succeeded.

If we close the server process first and only run the client process, we will get the following prompt:

root@server:~/cfadmin$ ./cfadmin -e script/client.lua 
[2021/11/11 17:11:50] [coroutine error] script/client.lua:6: Connection refused
stack traceback:
        script/client.lua:6: in main chunk

You're right. We can easily locate where the code went wrong

Code parsing

What makes it so easy for us to complete the network connection? Now let's go back to the previous code:

-- script/server.lua
local TCP = require "internal.TCP"

local server = TCP:new()

server:listen("127.0.0.1", 8080, function (fd, ip, port)
  local sock = TCP:new():set_fd(fd)

  print(fd, ip, port)

  sock:close()
end)
-- script/client.lua
local TCP = require "internal.TCP"

local client = TCP:new()

assert(client:connect("127.0.0.1", 8080))

print("Connection succeeded.")

client:close()

First, we import the TCP library into the client and server, and then create the required TCP Socket instances for each

Instances can be used to complete various network operations, such as send, sendfile, recv, readline, close, etc

But before these operations, we must first complete listen and connect! These 2 methods must be invoked before other network operations.

Therefore, we start to call the listen and connect methods on line 5, so that the basic operations on both sides are finished

1. listen(ip, port, callback)

The listen method has three required parameters:

  • ip - String type, which can specify the address to listen to;

  • port - Integer type, which specifies the port used to listen;

  • callback - Function type. The successfully connected client will trigger a callback;

The callback function prototype of callback is: function (fd, ip, port) end

  • fd - Integer type, file descriptor;

  • ip - String type, client connection address;

  • port - Integer type, client connection port;

The callback function will be injected with the above parameters, which will help you understand the source of the client

2. connect(ip, port)

The connect method has 2 required parameters:

  • ip - String type, which can specify the address to listen to;

  • port - Integer type, which specifies the port used to listen;

Return true for success, false for failure, and the error reason of string type

3. Blocking and non blocking

The server callback triggered by each connection establishment will create a workflow. Each workflow is a separate execution stack and independent of each other

Assuming that two links A and B are created and established at the same time, they will run in their respective processes, and A's Read will not affect B's Write

Because coprocessor and event driven realize real synchronization and non blocking, we can write asynchronous code in a synchronous way

4. Working mode

Note: Socket can only work in half duplex mode by default! As for why it is designed like this, we will discuss it in a subsequent article

5. Resource recovery

Each time the server accepts a new connection, it must create an object to manage the file descriptor. It is also the corresponding system allocated file descriptor

Lua's GC can't help me reasonably release fd resources, so we must actively close to release resources after use

last

In this chapter, we have learned the basic network application programming method of cfadmin. In the next chapter, we will learn how to write network applications for interaction

Posted by hash1 on Fri, 12 Nov 2021 20:29:31 -0800