0%

简介

  • linux nmap命令 详解

linux nmap命令 详解

nmap 是一个功能强大的网络扫描工具,可以用于探测主机、服务以及网络上的各种信息。它在网络安全领域广泛应用,可用于网络发现、漏洞扫描、服务版本探测等任务。下面是 nmap 命令的一些常见用法和选项:

基本用法:

1
nmap [扫描类型] [目标主机或网络]

常用扫描类型:

  • -sS:TCP SYN 扫描,常用于快速扫描。
  • -sT:TCP 连接扫描,完整连接的方式扫描,速度较慢。
  • -sU:UDP 扫描,用于扫描 UDP 端口。
  • -sF:FIN 扫描,发送 FIN 包给目标主机。
  • -sX:XMAS 扫描,发送 URG、PSH、FIN 标志给目标主机。
  • -sN:NULL 扫描,发送没有标志的 TCP 包给目标主机。

其他常用选项:

  • -p:指定要扫描的端口或端口范围。
  • -A:启用操作系统检测、服务版本检测、脚本扫描等一系列功能。
  • -O:对目标主机进行操作系统检测。
  • -T:指定扫描的速度/对目标主机进行操作系统检测。
  • -v:详细模式,显示更多信息。
  • -oN:将扫描结果保存到文件中。

示例:

  1. 扫描单个主机的常用端口:

    1
    nmap -p 1-1000 192.168.1.1
  2. 扫描整个子网的常见端口:

    1
    nmap -p 1-1000 192.168.1.0/24
  3. 启用操作系统检测和服务版本检测:

    1
    nmap -A 192.168.1.1
  4. 使用 TCP SYN 扫描对单个主机进行快速扫描:

    1
    nmap -sS 192.168.1.1
  5. 使用 NULL 扫描扫描目标主机:

    1
    nmap -sN 192.168.1.1
  6. 对目标主机进行操作系统检测:

    1
    nmap -O 192.168.1.1

nmap 提供了丰富的选项和功能,可以根据需要进行定制化的扫描。记得在使用 nmap 进行扫描时,遵守网络安全和法律法规,避免对未经授权的系统进行扫描。

linux nmap命令 常用技巧

当使用 nmap 进行网络扫描时,有一些常用的技巧可以帮助你更有效地执行扫描并获得更有用的信息。以下是一些常见的 nmap 技巧:

  1. 指定端口范围:使用 -p 选项可以指定要扫描的端口范围。例如,-p 1-1000 表示扫描端口范围从 1 到 1000。

  2. 指定多个主机:你可以在命令中指定多个目标主机,以便同时扫描它们。例如,nmap 192.168.1.1 192.168.1.2

  3. 扫描整个子网:使用 CIDR 表示法来指定整个子网。例如,nmap 192.168.1.0/24 将扫描 192.168.1.0 到 192.168.1.255 的所有主机。

  4. 快速扫描:使用 -F 选项进行快速扫描。它只扫描常用端口,速度更快。例如,nmap -F 192.168.1.1

  5. 启用操作系统检测:使用 -O 选项可以尝试识别目标主机的操作系统。例如,nmap -O 192.168.1.1

  6. 启用服务版本检测:使用 -sV 选项可以尝试识别目标主机上运行的服务的版本信息。例如,nmap -sV 192.168.1.1

  7. 脚本扫描nmap 包含许多脚本,可以执行各种任务,如漏洞探测、服务识别等。使用 --script 选项来指定要运行的脚本。例如,nmap --script vuln 192.168.1.1 将运行漏洞扫描脚本。

  8. 保存结果:使用 -oN 选项可以将扫描结果保存到文件中,方便后续分析。例如,nmap -oN scan_results.txt 192.168.1.1

  9. 扫描速度调整:使用 -T 选项可以调整扫描速度,范围从 0(最慢)到 5(最快)。例如,nmap -T4 192.168.1.1 将使用较快的扫描速度。

  10. 显示详细信息:使用 -v 选项可以显示更详细的扫描信息。例如,nmap -v 192.168.1.1

这些技巧可以帮助你更灵活、更高效地使用 nmap 进行网络扫描,并获取更全面的信息。

简介

  • p7zip命令 详解

linux p7zip命令 详解

p7zip 是一个基于7-Zip的开源文件压缩和解压缩工具,用于Linux平台。它提供了一个命令行界面,允许用户使用不同的选项来执行各种压缩和解压缩操作。以下是 p7zip 命令的一些常见用法和选项:

1. 压缩文件或目录:

1
7z a [压缩文件名].7z [要压缩的文件或目录]

2. 解压缩文件:

1
7z x [压缩文件名].7z

3. 列出压缩文件中的内容:

1
7z l [压缩文件名].7z

4. 使用密码进行压缩和解压缩:

1
2
7z a -p[密码] [压缩文件名].7z [要压缩的文件或目录]
7z x -p[密码] [压缩文件名].7z

5. 设置压缩级别:

1
7z a -mx=[压缩级别] [压缩文件名].7z [要压缩的文件或目录]

其中 [压缩级别] 是一个介于0和9之间的整数,0表示无压缩,9表示最高压缩率。

6. 指定压缩文件类型:

1
7z a -t[压缩文件类型] [压缩文件名].[后缀名] [要压缩的文件或目录]

例如,如果要创建一个tar格式的压缩文件:

1
7z a -ttar [压缩文件名].tar [要压缩的文件或目录]

7. 帮助和其他选项:

1
7z --help

这将显示 p7zip 命令的所有可用选项和帮助信息。

p7zip 命令非常灵活,并且可以用于各种情况下的文件压缩和解压缩操作。记住,在执行任何操作之前,最好先阅读它的帮助文档,以确保正确使用所需的选项。

linux p7zip命令 常用技巧

当使用 p7zip 命令时,以下是一些常用的技巧和技巧,可以提高效率并使操作更加方便:

  1. 批量压缩文件:使用通配符来压缩多个文件或目录。

    1
    7z a archive.7z file1.txt file2.txt directory/
  2. 压缩文件并排除指定文件或目录:通过使用 -x 选项,可以在压缩时排除特定的文件或目录。

    1
    7z a archive.7z directory/ -x!*.txt
  3. 显示压缩进度:通过使用 -bsp1 选项,可以在压缩或解压缩过程中显示进度百分比。

    1
    7z a -bsp1 archive.7z directory/
  4. 将压缩文件分卷:通过使用 -v 选项,可以将压缩文件分割成指定大小的卷。

    1
    7z a -v1m archive.7z directory/

    这会将压缩文件分割成1MB大小的卷。

  5. 加密压缩文件:通过使用 -p 选项,可以指定密码来加密压缩文件。

    1
    7z a -psecret archive.7z directory/
  6. 解压特定文件:通过使用 -o 选项,可以指定解压缩文件的输出目录。

    1
    7z x archive.7z -ooutput_directory/
  7. 压缩文件时保留文件权限:通过使用 -m0=Copy 选项,可以在压缩时保留文件的权限。

    1
    7z a -m0=Copy archive.7z directory/
  8. 使用其他压缩算法:除了默认的7z算法外,还可以使用其他压缩算法,如zip。

    1
    7z a -tzip archive.zip directory/

这些技巧可以帮助你更有效地使用 p7zip 命令,并根据需要进行自定义。记住查看命令的帮助文档,以了解更多可用选项和功能。

简介

  • linux系统下常见的问题及其解决方法

mv 目录非空

当你尝试使用 mv 命令移动一个非空目录时,你会发现 mv 只能在同一文件系统中移动目录,而不能跨文件系统移动非空目录。如果你确实需要移动一个非空目录,可以尝试以下方法:

  1. 使用 rsync 命令
    rsync 是一个功能强大的工具,可以用于将文件和目录从一个位置同步到另一个位置。

    1
    rsync -avz /path/to/source/directory /path/to/destination
  2. 使用 cp 命令复制然后删除原目录
    如果 rsync 不可用,你可以先使用 cp 命令递归复制目录,然后删除原目录。

    1
    2
    cp -r /path/to/source/directory /path/to/destination
    rm -rf /path/to/source/directory
  3. 使用 tar 命令打包和解包
    你可以使用 tar 命令先将目录打包,然后将包解压到目标位置。

    1
    2
    3
    4
    5
    tar -czf directory.tar.gz -C /path/to/source directory
    mv directory.tar.gz /path/to/destination
    cd /path/to/destination
    tar -xzf directory.tar.gz
    rm directory.tar.gz

你可以选择最适合你情况的方法来移动非空目录。

ubuntu 文件加个锁是什么意思

在 Ubuntu 中,给文件加锁通常有以下几种含义:

  1. 权限锁定:

    • 通过修改文件的权限,限制其他用户对该文件的访问和操作。
    • 可以使用 chmod 命令来设置文件的读、写、执行权限。
  2. 文件锁定:

    • 在多用户环境下,某个用户正在编辑一个文件时,可以对该文件进行锁定,防止其他用户同时编辑该文件。
    • 常见的文件编辑器如 gedit、vim 等都支持文件锁定功能。
  3. 加密锁定:

    • 使用加密技术对文件进行加密,只有拥有正确密钥的用户才能访问和编辑该文件。
    • Ubuntu 自带的加密文件系统 eCryptfs 就可以实现这种加密锁定。
  4. 共享锁定:

    • 在网络共享环境下,可以对文件设置共享锁定,限制其他用户的访问权限。
    • 这种锁定通常由文件服务器或共享服务来管理和实现。

总之,给 Ubuntu 中的文件加锁,主要是为了保护文件的安全性和完整性,防止未经授权的访问和修改。具体使用哪种锁定方式,需要根据实际需求和使用场景来决定。

  • 通过命令 chmod 777 destination 修改文件权限即可

简介

  • mongoose核心api笔记

struct mg_addr

  • 简介:

    • 该结构包含网络地址。它可以被认为sockaddr结构在Mongoose中的等价结构体
  • 原型:

    1
    2
    3
    4
    5
    6
    struct mg_addr {
    uint16_t port; // TCP or UDP port in network byte order
    uint32_t ip; // IP address in network byte order
    uint8_t ip6[16]; // IPv6 address
    bool is_ip6; // True when address is IPv6 address
    };

struct mg_mgr

  • 简介:

    • 它是一个事件管理结构体,能够保存一个正在活动的连接列表,以及一些维持管理的信息
  • 原型

    1
    2
    3
    4
    5
    6
    7
    8
    struct mg_mgr {
    struct mg_connection *conns; // List of active connections 结构体数组
    struct mg_dns dns4; // DNS for IPv4
    struct mg_dns dns6; // DNS for IPv6
    int dnstimeout; // DNS resolve timeout in milliseconds
    unsigned long nextid; // Next connection ID
    void *userdata; // Arbitrary user data pointer
    };

struct mg_connection

  • 简介:

    • 它是一个连接:可能是一个监听连接,或者是一个已接收连接,或者是一个出站连接
  • 原型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    struct mg_connection {
    struct mg_connection *next; // Linkage in struct mg_mgr :: connections
    struct mg_mgr *mgr; // Our container
    struct mg_addr loc; // Local address
    struct mg_addr rem; // Remote address
    void *fd; // Connected socket, or LWIP data
    unsigned long id; // Auto-incrementing unique connection ID
    struct mg_iobuf recv; // Incoming data
    struct mg_iobuf send; // Outgoing data
    mg_event_handler_t fn; // User-specified event handler function
    void *fn_data; // User-specified function parameter
    mg_event_handler_t pfn; // Protocol-specific handler function
    void *pfn_data; // Protocol-specific function parameter
    char label[50]; // Arbitrary label
    void *tls; // TLS specific data
    unsigned is_listening : 1; // Listening connection
    unsigned is_client : 1; // Outbound (client) connection
    unsigned is_accepted : 1; // Accepted (server) connection
    unsigned is_resolving : 1; // Non-blocking DNS resolve is in progress
    unsigned is_connecting : 1; // Non-blocking connect is in progress
    unsigned is_tls : 1; // TLS-enabled connection
    unsigned is_tls_hs : 1; // TLS handshake is in progress
    unsigned is_udp : 1; // UDP connection
    unsigned is_websocket : 1; // WebSocket connection
    unsigned is_hexdumping : 1; // Hexdump in/out traffic
    unsigned is_draining : 1; // Send remaining data, then close and free
    unsigned is_closing : 1; // Close and free the connection immediately
    unsigned is_full : 1; // Stop reads, until cleared
    unsigned is_resp : 1; // Response is still being generated
    unsigned is_readable : 1; // Connection is ready to read
    unsigned is_writable : 1; // Connection is ready to write
    };

mg_mgr_init

  • 简介:

    • 初始化事件管理器结构体变量,它所做的工作:
      • 将活动连接的列表设置为null
      • 设置IPv4和IPv6的默认DNS服务器
      • 设置默认DNS查找超时
  • 原型:

    1
    void mg_mgr_init(struct mg_mgr *mgr);
  • 参数:

    • mgr : 需要初始化的mg_mgr结构体指针
  • 返回值:

  • 示例:

    1
    2
    struct mg_mgr mgr;
    mg_mgr_init(&mgr);

mg_mgr_poll

  • 简介:

    • 在所有连接中迭代,接受新的连接,发送和接收数据,关闭连接并调用事件处理程序的功能,以适用于各自事件。
    • 执行一次池迭代(poll iteration)。对在mgr->conns列表中的每一个连接进行如下操作
      • 查看是否有传入数据。如果有,将数据读入到c->recv缓冲区,并发出一个MG_EV_READ事件
      • 查看c->send缓冲区是否有数据。如果有,写入数据,并发送MG_EV_WRITE事件
      • 如果一个连接处于监听状态,或已接收一个进入的连接状态,发送一个MG_EV_ACCEPT事件
      • 发送MG_EV_POLL事件
  • 原型:

    1
    void mg_mgr_poll(struct mg_mgr *mgr, int ms);
  • 参数:

    • mgr : 使用的事件管理结构体
    • ms : 超时时间,单位为毫秒
  • 返回值:

  • 示例:

    1
    while (running == true) mg_mgr_poll(&mgr, 1000 /*1 second*/);

mg_mgr_free

  • 简介:

    • 关闭所有连接,释放所有资源
  • 原型:

    1
    void mg_mgr_free(struct mg_mgr *mgr);
  • 参数:

    • mgr : 需要被清除的事件管理结构体
  • 返回值:

  • 示例:

    1
    2
    3
    4
    struct mg_mgr mgr;
    mg_mgr_init(&mgr);
    while (running == true) mg_mgr_poll(&mgr, 1000); // Event loop
    mg_mgr_free(&mgr);

mg_listen

  • 简介:

    • 创建一个监听连接,并将这个连接追加到mgr->conns连接列表中
  • 原型:

    1
    struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fn_data);
  • 参数:

    • mgr : 使用的事件管理结构体
    • url : URL。指定监听的本地IP地址和端口,例如:tcp://127.0.0.1:1234udp://0.0.0.0:9000
    • fn : 事件处理函数
    • fn_data : 一个任意指针,当事件处理函数被调用时,它会被作为fn_data传递。这个指针作为c->fn_data存储在连接结构体中
  • 返回值:

    • 成功,返回创建的连接
    • 失败,返回NULL
  • 示例:

    1
    struct mg_connection *c = mg_listen(&mgr, "tcp://127.0.0.1:8080", fn, NULL);

mg_connect

  • 简介:

    • 创建一个出站连接,并将这个连接追加到mgr->conns队列中
  • 原型:

    1
    struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fn_data);
  • 参数

    • mgr : 使用的事件管理结构体
    • url : URL,指定需要连接的远程IP地址和端口。例如:http://a.com
    • fn : 一个事件处理函数
    • fn_data : 一个任意指针,当事件处理函数被调用时,它会被作为fn_data传递。这个指针作为c->fn_data存储在连接结构体中
  • 返回值:

    • 成功,返回创建的连接
    • 失败,返回NULL
  • 示例:

    1
    struct mg_connection *c = mg_connect(&mgr, "http://example.org", fn, NULL);

mg_send

  • 简介:

    • 将大小为size的数据追加到c->send缓冲区。返回追加的字节数
  • 原型

    1
    int mg_send(struct mg_connection *c, const void *data, size_t size);
  • 参数:

    • c : 一个连接指针
    • data : 一个指向需要增加到输出缓冲区的数据指针
    • size : 数据大小
  • 返回值:

    • 成功, true
    • 失败, false
  • 详解:

    • 这个函数不会将数据推送到网络。它仅仅是将数据追加到输出缓冲区。
    • 只有当mg_mgr_poll()被调用时,才会将数据发送出去。
    • 如果mg_send()被多次调用,则输出缓冲区会增长
  • 示例

    1
    mg_send(c, "hi", 2);  // Append string "hi" to the output buffer

mg_printf

  • 简介:

    • mg_send()相同,但是使用printf()语义格式化数据。返回追加到输出缓冲区的字节数。有关支持格式规范列表,参见mg_snprintf
  • 原型:

    1
    int mg_printf(struct mg_connection *, const char *fmt, ...);
  • 参数:

    • c : 一个连接指针
    • fmt : printf()语义中的格式字符串
  • 返回值:

    • 返回追加到输出缓冲区的字节数
  • 示例:

    1
    mg_printf(c, "Hello, %s!", "world"); // Add "Hello, world!" to output buffer

mg_wrapfd

  • 简介:

    • 将给定的文件描述符fd包装到连接中,然后将该连接添加到事件管理器中。这个fd文件描述符必须支持send(), recv(), select()系统调用,而且是非阻塞的。Mongoose将把它当做TCP套接字使用。c->remc->loc地址将会变为空的
  • 原型:

    1
    struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd, mg_event_handler_t fn, void *fn_data);
  • 参数:

    • fd : 需要包装的文件描述符
    • mgr : 一个事件管理结构体
    • fn : 一个指向事件处理函数的指针
    • ud : 一个用户数据指针。它将被当做fn_data参数传递给fn
  • 返回值:

    • 成功,返回创建的连接
    • 失败,返回NULL

mg_mkpipe

  • 简介:

    • 创建两个互相连接的套接字,用于线程间通信。其中一个套接字被包装到一个Mongoose连接,并被添加到事件管理结构体中。另一个套接字将会被返回,且它应该被传递给工作线程。当一个工作线程使用send()发送任何数据到这个套接字,都将唤醒mgrfn事件处理函数接收一个MG_EV_READ事件。另外,fn向工作线程发送的任何数据,都被由工作线程使用recv()接收
  • 原型

    1
    int mg_mkpipe(struct mg_mgr *mgr, mg_event_handler_t fn, void *fn_data, bool udp);
  • 参数:

    • mgr : 一个事件管理结构体
    • fn : 一个指向事件处理函数的指针
    • fn_data : 一个指向用户数据的指针。它将会被当做fn_data参数传递给fn
    • udp : 告知创建一个UDP,还是创建一个TCP socketpair
  • 返回值:

    • 成功,返回创建的套接字
    • 失败,返回-1
  • 示例:

    • 参考examples/multi-threaded

mg_hello

  • 简介:

    • 便利功能,在给定的监听URL上启动一个简单的Web服务器。这个函数只有在接收到一个/quit请求才会返回。服务器处理以下URI
      • /quit – 退出服务,且退出函数
      • /debug – 设置调试级别,作为POST负载,{"level" : 3}是有效的
      • 对其他所有的URI,都将返回一个hi作为响应
  • 原型:

    1
    void mg_hello(const char *url);
  • 参数:

    • url : 一个监听的URL,例如:http://0.0.0.0:8000
  • 返回值:

简介

  • 文件相关api

struct mg_fd

  • 简介:

    • 文件系统虚拟化层
    • Mongoose允许覆盖文件IO操作,以支持不同的存储设备,如可编程的闪存,无文件系统设备等。为了实现这一点,Mongoose提供了一个结构mg_fs API来指定一个自定义的文件系统。除此之外,Mongoose还提供了几个内置的API–一个标准的POSIX,FatFS,和一个 “打包的FS “API:
      1
      2
      3
      extern struct mg_fs mg_fs_posix;   // POSIX open/close/read/write/seek
      extern struct mg_fs mg_fs_packed; // Packed FS, see examples/device-dashboard
      extern struct mg_fs mg_fs_fat; // FAT FS
  • 原型:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    struct mg_fs {
    int (*st)(const char *path, size_t *size, time_t *mtime); // stat file
    void (*ls)(const char *path, void (*fn)(const char *, void *), void *);
    void *(*op)(const char *path, int flags); // Open file
    void (*cl)(void *fd); // Close file
    size_t (*rd)(void *fd, void *buf, size_t len); // Read file
    size_t (*wr)(void *fd, const void *buf, size_t len); // Write file
    size_t (*sk)(void *fd, size_t offset); // Set file position
    bool (*mv)(const char *from, const char *to); // Rename file
    bool (*rm)(const char *path); // Delete file
    bool (*mkd)(const char *path); // Create directory
    };

    enum { MG_FS_READ = 1, MG_FS_WRITE = 2, MG_FS_DIR = 4 };

struct mg_fd

  • 简介:

    • 已打开的文件抽象。
  • 原型:

    1
    2
    3
    4
    struct mg_fd {
    void *fd;
    struct mg_fs *fs;
    };

mg_fs_open

  • 简介:

    • 在一个给定的文件系统中打开一个文件
  • 原型:

    1
    struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags);
  • 参数:

    • fs : 一个文件系统的实现
    • path : 一个文件路径
    • flags : 所需的标志,是MG_FS_READ和MG_FS_WRITE的组合。
  • 返回值:

    • 成功: 一个非NULL的已打开的描述符、
    • 失败: NULL
  • 示例

    1
    struct mg_fd *fd = mg_fs_open(&mg_fs_posix, "/tmp/data.json", MG_FS_WRITE);

mg_fs_close

  • 简介:

    • 关闭一个已打开的文件描述符
  • 原型:

    1
    void mg_fs_close(struct mg_fd *fd);
  • 参数:

    • fd : 一个已打开的文件描述符
  • 返回自:

mg_file_read

  • 简介:

    • 在内存中读取整个文件。
  • 原型

    1
    char *mg_file_read(struct mg_fs *fs, const char *path, size_t *size);
  • 参数

    • fs : 一个文件系统的实现
    • path : 一个文件路径
    • size : 如果不是NULL,将包含所读文件的大小。
  • 返回值:

    • 成功时,一个指向文件数据的指针,该指针保证为0端。
    • 错误时,为NULL
  • 示例:

    1
    2
    size_t size = 0;
    char *data = mg_file_read(&mg_fs_packed, "/data.json", &size);

mg_file_write

  • 简介:

    • 写入一段数据buf,len到一个文件路径。如果该文件不存在,它将被创建。之前的内容,如果有的话,会被删除。
  • 原型:

    1
    bool mg_file_write(struct mg_fs *fs, const char *path, const void *buf, size_t len);
  • 参数:

    • fs : 一个文件系统的实现
    • path : 一个文件路径
    • buf : 一个指向待写数据的指针
    • len : 待写数据的大小
  • 返回值:

    • 成功, true
    • 失败, false
  • 示例:

    1
    mg_file_write(&mg_fs_fat, "/test.txt", "hi\n", 3);

mg_file_printf

  • 简介:

    • 写一个打印格式的数据到一个文件路径。如果该文件不存在,它将被创建。之前的内容(如果有的话)被删除
  • 原型:

    1
    bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...);
  • 参数:

    • fs : 一个文件系统的实现
    • path : 一个文件路径
    • fmt : printf语义中的格式字符串。支持的格式指定器的列表见mg_snprintf。
  • 返回值:

    • 成功, true
    • 失败, false
  • 示例:

    1
    mg_file_printf(&mg_fs_fat, "/test.txt", "%s\n", "hi");

简介

  • 使用方式

    • 添加mongoose.hmongoose.c文件
  • 两个基本数据结构

    • struct mg_mgr – 持有所有运行连接的事件管理
    • struct mg_connection – 单个连接描述符。换言之,每个连接都通过结构mg_connection结构来描述
  • 事件处理,每一个连接有两个事件处理函数:c->fnc->pfn

    • c->fn,是由用户自定义的事件处理函数
    • c->pfn,是一个特定于协议的处理程序函数,被隐式设置。例如,mg_http_listen()c->pfn设置为mongoose的HTTP事件处理程序。
  • 在特定于用户的处理程序之前调用特定于协议的处理程序。它解析传入数据,并可能调用特定于协议的事件,例如MG_EV_HTTP_MSG

  • 注意:

    • 由于Mongoose的核心不受并发访问的保护,因此请确保从同一线程或RTOS任务调用所有mg_* API函数
  • 发送和接收缓冲区,每一个连接有一个发送和接收缓冲区:struct mg_connection::send, struct mg_connection::recv

    • struct mg_connection::send : 将发送到对端的数据
    • struct mg_connection::recv : 从对端接收的数据
  • 当数据到达时,mongoose将接收到的数据追加到recv并触发一个MG_EV_READ事件。

  • 用户可以通过调用输出函数之一来发送数据,例如mg_send()mg_printf()或类似于mg_ws_send()的协议特定函数。

  • 输出函数将数据追加到send缓冲区。当mongoose成功将数据写入套接字中时,它会将数据从结构体mg_connection::send中丢掉并且发送一个MG_EV_WRITE事件

  • 每个连接都有与之关联的事件处理函数,该功能必须由用户实现。事件处理函数是mongoose的关键要素,因为它定义了连接的行为

  • 事件处理函数示例:

    1
    2
    3
    4
    5
    6
    7
    // Event handler function defines connection's behavior
    static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_READ) {
    mg_send(c, c->recv.buf, c->recv.len); // Implement echo server
    c->recv.len = 0; // Delete received data
    }
    }
  • 参数:

    • struct mg_connection *c – 接收事件的连接
    • int ev – 在mongoose.h中定义的事件编号。例如,当数据到达入站连接时,ev将是MG_EV_READ
    • void *ev_data – 指向特定于事件的数据,并且对不同事件具有不同的含义。
      • 例如,对于MG_EV_READ事件,ev_data是一个int *指向从远程对等方接收的字节数,并保存到c->recv IO缓冲区中。
      • ev_data的确切含义是用来描述每一个事件
      • 特定于协议的事件通常将ev_data指向具有特定协议信息的结构
    • void *fn_data – 连接的用户定义指针,这是用于应用程序特定数据的占位符。
      • 这个fn_data指针是在*_listen()或者*_connect()调用期间设置的,并将其存储在c->fn_data
      • 监听连接将c->fn_data的值复制到新接受的连接,因此所有接受的连接最初共享相同的fn_data指针。
      • 通过设置c->fn_data = new_value,可以随时更新或替换任何连接的fn_data指针
  • struct mg_connection具有带有连接标志的设置。标志是二进制的:它们是0或者1。一些标志是由mongoose设置的,应用代码不能修改。例如,is_udp标志告诉应用连接是不是UDP。

  • 一些标志是应用代码可以修改的,它们是:is_hexdumping, id_draining, is_closing

    • id_draining标志,如果用户设置了这个标志,就是告诉mongoose向对端发送剩余数据,当都发送完毕时,关掉这个连接
    • is_closing标志,如果用户设置了这个标志,就是立即关闭并释放连接,而不需要发送剩余数据
    • is_hexdumping标志,
  • 调试日志。要增加调试的详细性,调用mg_log_set()mg_log_set(MG_LL_DEBUG); mg_mgr_init(&mgr);

    • MG_INFO(), MG_DEBUG()日志宏默认情况下使用putchar(),即它们使用标准的C stdout流。这种方式在传统的操作系统环境正常工作。在嵌入式环境中,为了查看调试日志,可以使用两种方式:IO重定位和日志重定向
      • IO重定位可以通过嵌入式SDK实现
  • 如果您需要执行连接的任何初始化,请通过捕获MG_EV_OPEN事件进行操作。

  • 该事件是在连接被分配并添加到事件管理之后立即发送的,并在其他任何内容之前。

    1
    2
    3
    4
    static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_OPEN) {
    ... // Do your initialisation
    }
  • 如果您需要保留一些特定连接的数据,则有两个选择

    • 第一,使用c->fn_data指针。该指针作为最后一个参数传递给事件处理程序
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
      if (ev == MG_EV_OPEN) {
      c->fn_data = malloc(123); // Change our fn_data
      } else if (ev == MG_EV_CLOSE) {
      free(fn_data); // Don't forget to free!
      }
      ...
      }

      // Every accepted connection inherit NULL pointer as c->fn_data, but we change
      // it per-connection to something else
      mg_http_listen(&mgr, "http://localhost:1234", fn, NULL);
    • 第二,使用c->label缓冲区。该缓冲区可以容纳一些特定于连接的数据,而无需额外的内存分配
      1
      2
      3
      4
      static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
      if (ev == MG_EV_WS_OPEN) {
      c->label[0] = 'W'; // Established websocket connection, store something
      ...
  • 如果需要关闭连接,请在自己的事件处理函数中设置c->is_draining = 1;。它将告诉mongoose向对端发送剩余数据,当都发送完毕时,关掉这个连接

  • 如果需要立即关闭而不需要发送剩余数据,则设置c->is_closing = 1;

  • 使用mg_http_reply()函数创建HTTP响应报文。重要的是,这个函数能够正确设置Content-Length头。

  • 当然,也可以手动创建HTTP响应报文。例如,使用mg_printf()函数,但是请确定设置了Content-Length

    • mg_printf(c, "HTTP/1.1 200 OK\r\Content-Length: %d\r\n\r\n%s", 2, "hi");
  • 或者,使用块的传输编码:

    1
    2
    3
    4
    mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
    mg_http_printf_chunk(c, "%s", "foo");
    mg_http_printf_chunk(c, "%s", "bar");
    mg_http_printf_chunk(c, ""); // Don't forget the last empty chunk
  • 需要注意的是:如果不适用mg_http_reply()或者mg_http_*_chunk(),请确保在自己的活动处理程序完成写入响应报文时,确保设置c->is_reply = 0;

  • 默认情况下,IO缓冲区分配的大小MG_IO_SIZE是2048.将其更改为512可以减少每个连接的内存消耗

  • Mongoose有三种影响构建的构建常数(预处理器定义):目标体系结构/操作系统,目标网络堆栈,可调参数。

  • 为了在构建时间设置选项,请使用-D选项编译器标志

    1
    2
    3
    4
    $ cc app.c mongoose.c                           # Use defaults!
    $ cc app.c mongoose.c -D MG_ENABLE_IPV6=1 # Build with IPv6 enabled
    $ cc app.c mongoose.c -D MG_ARCH=MG_ARCH_RTX # Set architecture
    $ cc app.c mongoose.c -D MG_ENABLE_SSI=0 -D MG_IO_SIZE=8192 # Multiple options
  • 支持架构的列表在Arch.H标题文件中定义。通常,无需明确指定体系结构。在构建过程中猜到了架构,因此通常不需要设置

  • 网络堆栈常数在下面列出。请注意,如果未指定网络堆栈,则假定目标体系结构支持标准BSD套接字API

  • 另一类的构建常量是在src/config.h中定义的,以及它们的默认值。这些是包含/排除某个功能或更改相关参数的调谐物。

  • MG_IO_SIZE常数还设置了最大的UDP消息大小,请参见#/907有关详细信息。如果应用程序使用大型UDP消息,请相应地增加MG_IO_SIZE限制。

  • 此步骤是可选的,仅当您打算使用自定义TCP/IP堆栈时才需要。为此,您应该:

    • 禁用BSD插座API:在Mongoose_custom.h中,添加#define MG_ENABLE_SOCKET 0
  • 添加几个内部API函数的实现,例如mg_send(), mg_mgr_poll()等等。要参考,请查看test/mongoose_custom.c和实验性的src/mip.c

重要API

1.1 数据结构

struct mg_addr

1
2
3
4
5
6
struct mg_addr {
uint16_t port; // TCP or UDP port in network byte order
uint32_t ip; // IP address in network byte order
uint8_t ip6[16]; // IPv6 address
bool is_ip6; // True when address is IPv6 address
};
  • 该结构包含网络地址。它可以被认为sockaddr结构在Mongoose中的等价结构体

struct mg_mgr

1
2
3
4
5
6
7
8
struct mg_mgr {
struct mg_connection *conns; // List of active connections 结构体数组
struct mg_dns dns4; // DNS for IPv4
struct mg_dns dns6; // DNS for IPv6
int dnstimeout; // DNS resolve timeout in milliseconds
unsigned long nextid; // Next connection ID
void *userdata; // Arbitrary user data pointer
};
  • 它是一个事件管理结构体,能够保存一个正在活动的连接列表,以及一些维持管理的信息

struct mg_connection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct mg_connection {
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
struct mg_mgr *mgr; // Our container
struct mg_addr loc; // Local address
struct mg_addr rem; // Remote address
void *fd; // Connected socket, or LWIP data
unsigned long id; // Auto-incrementing unique connection ID
struct mg_iobuf recv; // Incoming data
struct mg_iobuf send; // Outgoing data
mg_event_handler_t fn; // User-specified event handler function
void *fn_data; // User-specified function parameter
mg_event_handler_t pfn; // Protocol-specific handler function
void *pfn_data; // Protocol-specific function parameter
char label[50]; // Arbitrary label
void *tls; // TLS specific data
unsigned is_listening : 1; // Listening connection
unsigned is_client : 1; // Outbound (client) connection
unsigned is_accepted : 1; // Accepted (server) connection
unsigned is_resolving : 1; // Non-blocking DNS resolve is in progress
unsigned is_connecting : 1; // Non-blocking connect is in progress
unsigned is_tls : 1; // TLS-enabled connection
unsigned is_tls_hs : 1; // TLS handshake is in progress
unsigned is_udp : 1; // UDP connection
unsigned is_websocket : 1; // WebSocket connection
unsigned is_hexdumping : 1; // Hexdump in/out traffic
unsigned is_draining : 1; // Send remaining data, then close and free
unsigned is_closing : 1; // Close and free the connection immediately
unsigned is_full : 1; // Stop reads, until cleared
unsigned is_resp : 1; // Response is still being generated
unsigned is_readable : 1; // Connection is ready to read
unsigned is_writable : 1; // Connection is ready to write
};
  • 它是一个连接:可能是一个监听连接,或者是一个已接收连接,或者是一个出站连接

1.2 核心API调用

mg_mgr_init()

  • void mg_mgr_init(struct mg_mgr *mgr);
  • 初始化事件管理器结构体变量,它所做的工作:
    • 将活动连接的列表设置为null
    • 设置IPv4和IPv6的默认DNS服务器
    • 设置默认DNS查找超时
  • 参数
    • mgr – 需要初始化的mg_mgr结构体指针
  • 返回值:无
  • 示例
    1
    2
    struct mg_mgr mgr;
    mg_mgr_init(&mgr);

mg_mgr_poll()

  • void mg_mgr_poll(struct mg_mgr *mgr, int ms);
  • 在所有连接中迭代,接受新的连接,发送和接收数据,关闭连接并调用事件处理程序的功能,以适用于各自事件。
  • 执行一次池迭代(poll iteration)。对在mgr->conns列表中的每一个连接进行如下操作
    • 查看是否有传入数据。如果有,将数据读入到c->recv缓冲区,并发出一个MG_EV_READ事件
    • 查看c->send缓冲区是否有数据。如果有,写入数据,并发送MG_EV_WRITE事件
    • 如果一个连接处于监听状态,或已接收一个进入的连接状态,发送一个MG_EV_ACCEPT事件
    • 发送MG_EV_POLL事件
  • 参数
    • mgr – 使用的事件管理结构体
    • ms – 超时时间,单位为毫秒
  • 返回值:无
  • 示例
    • while (running == true) mg_mgr_poll(&mgr, 1000 /*1 second*/);

mg_mgr_free()

  • void mg_mgr_free(struct mg_mgr *mgr);
  • 关闭所有连接,释放所有资源
  • 参数:
    • mgr – 需要被清除的事件管理结构体
  • 返回值:无
  • 示例
    1
    2
    3
    4
    struct mg_mgr mgr;
    mg_mgr_init(&mgr);
    while (running == true) mg_mgr_poll(&mgr, 1000); // Event loop
    mg_mgr_free(&mgr);

mg_listen()

  • struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fn_data);
  • 创建一个监听连接,并将这个连接追加到mgr->conns连接列表中
  • 参数:
    • mgr – 使用的事件管理结构体
    • url – URL。指定监听的本地IP地址和端口,例如:tcp://127.0.0.1:1234udp://0.0.0.0:9000
    • fn – 事件处理函数
    • fn_data – 一个任意指针,当事件处理函数被调用时,它会被作为fn_data传递。这个指针作为c->fn_data存储在连接结构体中
  • 返回值:返回创建的连接 或 NULL作为错误
  • 示例
    • struct mg_connection *c = mg_listen(&mgr, "tcp://127.0.0.1:8080", fn, NULL);

mg_connect()

  • struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fn_data);
  • 创建一个出站连接,并将这个连接追加到mgr->conns队列中
  • 参数:
    • mgr – 使用的事件管理结构体
    • url – URL,指定需要连接的远程IP地址和端口。例如:http://a.com
    • fn – 一个事件处理函数
    • fn_data – 一个任意指针,当事件处理函数被调用时,它会被作为fn_data传递。这个指针作为c->fn_data存储在连接结构体中
  • 返回值:返回创建的连接 或 NULL作为错误
  • 注意:
    • 这个函数不会连接对端,它只会分配需要的资源和启动连接进程。
    • 一旦对端真正连接了,会将MG_EV_CONNECT事件发送到连接事件处理
  • 示例
    • struct mg_connection *c = mg_connect(&mgr, "http://example.org", fn, NULL);

mg_send()

  • int mg_send(struct mg_connection *c, const void *data, size_t size);
  • 将大小为size的数据追加到c->send缓冲区。返回追加的字节数
  • 注意:
    • 这个函数不会将数据推送到网络。它仅仅是将数据追加到输出缓冲区。
    • 只有当mg_mgr_poll()被调用时,才会将数据发送出去。
    • 如果mg_send()被多次调用,则输出缓冲区会增长
  • 参数:
    • c – 一个连接指针
    • data – 一个指向需要增加到输出缓冲区的数据指针
    • size – 数据大小
  • 返回值:如果数据成功追加,则返回true;否则返回false
  • 示例
    • mg_send(c, "hi", 2); // Append string "hi" to the output buffer

mg_printf(), mg_vprintf()

  • int mg_printf(struct mg_connection *, const char *fmt, ...);
  • int mg_vprintf(struct mg_connection *, const char *fmt, va_list *ap);
  • mg_send()相同,但是使用printf()语义格式化数据。返回追加到输出缓冲区的字节数。有关支持格式规范列表,参见mg_snprintf
  • 参数:
    • c – 一个连接指针
    • fmtprintf()语义中的格式字符串
  • 返回值:返回追加到输出缓冲区的字节数
  • 示例
    • mg_printf(c, "Hello, %s!", "world"); // Add "Hello, world!" to output buffer

mg_wrapfd()

  • struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd, mg_event_handler_t fn, void *fn_data);
  • 将给定的文件描述符fd包装到连接中,然后将该连接添加到事件管理器中。这个fd文件描述符必须支持send(), recv(), select()系统调用,而且是非阻塞的。Mongoose将把它当做TCP套接字使用。c->remc->loc地址将会变为空的
  • 参数:
    • fd – 需要包装的文件描述符
    • mgr – 一个事件管理结构体
    • fn – 一个指向事件处理函数的指针
    • ud – 一个用户数据指针。它将被当做fn_data参数传递给fn
  • 返回值:返回创建的连接 或者 NULL作为错误

mg_mkpipe()

  • int mg_mkpipe(struct mg_mgr *mgr, mg_event_handler_t fn, void *fn_data, bool udp);
  • 创建两个互相连接的套接字,用于线程间通信。其中一个套接字被包装到一个Mongoose连接,并被添加到事件管理结构体中。另一个套接字将会被返回,且它应该被传递给工作线程。当一个工作线程使用send()发送任何数据到这个套接字,都将唤醒mgrfn事件处理函数接收一个MG_EV_READ事件。另外,fn向工作线程发送的任何数据,都被由工作线程使用recv()接收。
  • 参数:
    • mgr – 一个事件管理结构体
    • fn – 一个指向事件处理函数的指针
    • fn_data – 一个指向用户数据的指针。它将会被当做fn_data参数传递给fn
    • udp – 告知创建一个UDP,还是创建一个TCP socketpair
  • 返回值:成功,返回创建的套接字;失败,返回-1
  • 使用案例参见examples/multi-threaded

mg_hello()

  • void mg_hello(const char *url);
  • 便利功能,在给定的监听URL上启动一个简单的Web服务器。这个函数只有在接收到一个/quit请求才会返回。服务器处理以下URI
    • /quit – 退出服务,且退出函数
    • /debug – 设置调试级别,作为POST负载,{"level" : 3}是有效的
    • 对其他所有的URI,都将返回一个hi作为响应
  • 参数:
    • url – 一个监听的URL,例如:http://0.0.0.0:8000

1.3 HTTP API

struct mg_http_header

  • 声明:
    1
    2
    3
    4
    struct mg_http_header {
    struct mg_str name; // Header name
    struct mg_str value; // Header value
    };
  • 结构代表HTTP标头,像Content-Type: text/htmlContent-Type 是一个 Header name,text/html/是一个 Header value

struct mg_http_message

  • 声明
    1
    2
    3
    4
    5
    6
    struct mg_http_message {
    struct mg_str method, uri, query, proto; // Request/response line
    struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers
    struct mg_str body; // Body
    struct mg_str message; // Request line + headers + body
    };
  • 结构代表HTTP消息。

mg_http_listen()

  • struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fn_data);
  • 创建HTTP侦听器。
  • 参数:
    • mgr – 一个事件管理结构体
    • url – 一个URL,指定监听的本地IP地址和端口。例如:http://0.0.0.0:8000
    • fn – 一个事件处理函数
    • fn_data – 一个任意指针,当事件处理函数被调用时,它会被作为fn_data传递。这个指针作为c->fn_data存储在连接结构体中
  • 返回值:返回一个指向创建的连接指针 或者 返回NULL表示错误
  • 示例
    1
    2
    struct mg_connection *c = mg_http_listen(&mgr, "0.0.0.0:8000", fn, arg);
    if (c == NULL) fatal_error("Cannot create listener");

mg_http_connect()

  • struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url, mg_event_handler_t fn, void *fn_data);
  • 创建HTTP客户端连接。这个函数不能连接到对端,它仅仅分配需要的资源和启动连接进程。当对端真正连接好了,会向连接事件处理函数发送一个MG_EV_CONNECT事件
  • 参数:
    • mgr – 事件管理结构体
    • url – URL,指定远程URL。例如:http://google.com
    • fn – 事件处理函数
    • fn_data – 一个任意指针,当事件处理函数被调用时,它会被作为fn_data传递。这个指针作为c->fn_data存储在连接结构体中
  • 返回值: 返回一个指向创建的连接的指针 或者 返回NULL表示错误
  • 示例
    1
    2
    struct mg_connection *c = mg_http_connect(&mgr, "http://google.com", fn, NULL);
    if (c == NULL) fatal_error("Cannot create connection");

mg_http_status()

  • int mg_http_status(const struct mg_http_message *hm);
  • 获取HTTP响应的状态代码。
  • 参数:
    • hm – 需要解析的HTTP响应
  • 返回值:返回状态码。例如:200表示成功

mg_http_get_request_len()

  • int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
  • 获取请求的长度。请求的长度是直到HTTP头结束的字节数。它不包括HTTP请求体的长度
  • 参数:
    • buf – 指向存放请求数据的缓冲区的指针
    • buf_len – 缓冲区大小
  • 返回值:
    • -1 – 错误
    • 0 – 消息不完整
    • 请求的长度
  • 示例
    1
    2
    const char *buf = "GET /test \n\nGET /foo\n\n";
    int req_len = mg_http_get_request_len(buf, strlen(buf)); // req_len == 12

mg_http_parse()

  • int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm);
  • 解析请求报文字符串,并存入到mg_http_message结构体中
  • 参数:
    • s – 一个请求字符串
    • len – 请求字符串的长度
    • hm – 存储解析请求报文结果的结构体指针
  • 返回值:返回请求报文的长度
  • 示例
    1
    2
    3
    struct mg_http_message hm;
    const char *buf = "GET / HTTP/1.0\n\n";
    if (mg_http_parse(buf, strlen(buf), &hm) > 0) { /* success */ }

mg_http_printf_chunk()

  • void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...);
  • 使用printf()语义,写一个块编码的块数据。(Write a chunk of data in chunked encoding format, using printf() semantic)
  • 参数:
    • c – 一个连接指针
    • fmt – 以printf()语义的字符串
  • 返回值:无
  • 示例
    • mg_http_printf_chunk(c, "Hello, %s!", "world");

mg_http_write_chunk()

  • void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len);
  • 写入一个块编码格式的块数据(Write a chunk of data in chunked encoding format.)
  • 参数:
    • c – 一个连接指针
    • buf – 需要写入的数据
    • len – 写入数据的长度
  • 返回值:无
  • 示例:
    • mg_http_write_chunk(c, "hi", 2);

mg_http_delete_chunk()

  • void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm);
  • 从输入缓冲区中删除指定的块(chunk)
  • 参数:
    • c – 连接指针
    • hm – 需要删除的块(chunk)
  • 返回值:无
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_CHUNK) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    mg_http_delete_chunk(c, hm); // Remove received chunk
    }
    }

struct mg_http_serve_opts

  • 声明:
    1
    2
    3
    4
    5
    6
    7
    8
    struct mg_http_serve_opts {
    const char *root_dir; // Web root directory, must be non-NULL
    const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
    const char *extra_headers; // Extra HTTP headers to add in responses
    const char *mime_types; // Extra mime types, ext1=type1,ext2=type2,..
    const char *page404; // Path to the 404 page, or NULL by default
    struct mg_fs *fs; // Filesystem implementation. Use NULL for POSIX
    };
  • 传递给mg_http_serve_dir()mg_http_serve_file()的结构,该结构驱动了这两个函数的行为

mg_http_serve_dir()

  • void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, const struct mg_http_serve_opts *opts);
  • 根据给定选项服务多个静态文件。文件也可以被压缩,包括目录索引。所有压缩文件都必须以.gz结尾,并且不得在没有扩展名的情况下存在具有相同名称的文件,否则将优先考虑
  • 注意:
    • 为了启动SSI,需要设置-DMSG_ENABLE_SSI=1构件标志
    • root_dir中为了避免双点..,如果需要引用高级目录,则需要使用绝对路径
  • 参数:
    • c – 使用的连接
    • hm – 应该被服务的HTTP消息
    • opts – 服务选项。请注意,opts.root_dir可以选择接受额外的逗号分隔uri=path
  • 返回值:无
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    struct mg_http_serve_opts opts;
    memset(&opts, 0, sizeof(opts));
    opts.root_dir = "/var/www,/conf=/etc"; // Serve /var/www. URIs starting with /conf are served from /etc
    mg_http_serve_dir(c, hm, &opts);
    }
    }

mg_http_serve_file()

  • void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm, const char *path, struct mg_http_serve_opts *opts);
  • 服务一个静态文件。如果不存在带有路径中指定的文件名的文件,则Mongoose尝试附加.gz;如果存在这样的文件,它将使用Content-Encoding: gzip header 去服务
  • 注意:
    • opts->root_dir设置被这个函数忽略
    • opts->extra_headers 必须以\r\n结束
  • 参数:
    • c – 使用的连接
    • hm – 需要服务的HTTP消息
    • path – 需要服务的文件路径
    • opts – 服务选项
  • 返回值:无
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    struct mg_http_serve_opts opts = {
    .mime_types = "png=image/png",
    .extra_headers = "AA: bb\r\nCC: dd\r\n"
    };
    mg_http_serve_file(c, hm, "a.png", &opts);
    }
    }

mg_http_reply()

  • void mg_http_reply(struct mg_connection *c, int status_code, const char *headers, const char *body_fmt, ...);
  • 通过使用printf()语义发送简单的HTTP响应。这个函数根据body_fmt格式化响应体(response body),然后自动追加到一个正确的Content-Length头(header)。额外的headers需要通过headers参数传递
  • 参数:
    • c – 使用的连接
    • status_code – 一个HTTP响应状态码
    • headers – 额外的headers,默认为NULL,如果不是空,则必须以\r\n结尾
    • fmt – 使用printf语义,需要格式化成HTTP body的字符串
  • 返回值:无
  • 示例:
    • 发送一个简单的JSON响应:
      • mg_http_reply(c, 200, "Content-Type: application/json\r\n", "{\"result\": %d}", 123);
    • 发送一个302重定向:
      • mg_http_reply(c, 302, "Location: /\r\n", "");
    • 发送一个错误
      • mg_http_reply(c, 403, "", "%s", "Not Authorized\n");

mg_http_get_header()

  • struct mg_str *mg_http_get_header(struct mg_http_message *hm, const char *name);
  • 获取HTTP header值
  • 参数:
    • hm – 需要寻找 header 的HTTP消息
    • name – Header name
  • 返回值:HTTP header 值 或 NULL表示没有找到
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Mongoose event handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    struct mg_str *s = mg_http_get_header(hm, "X-Extra-Header");
    if (s != NULL) {
    mg_http_reply(c, 200, "", "Holly molly! Header value: %.*s", (int) s->len, s->ptr);
    } else {
    mg_http_reply(c, 200, "", "Oh no, header is not set...");
    }
    }
    }

mg_http_get_header_var()

  • struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
  • 解析具有表格name1=value1; name=value2;...的HTTP header,并获取一个给定的变量
  • 参数:
    • s – HTTP header
    • name – 变量名字的名字
  • 返回值:一个请求的变量 或 一个空的字符串
  • 示例:
    1
    2
    3
    4
    5
    6
    struct mg_str *cookie = mg_http_get_header(hm, "Cookie");
    struct mg_str token = mg_str("");

    if (cookie != NULL) {
    token = mg_http_get_header_var(*cookie, mg_str("access_token"));
    }

mg_http_var()

  • struct mg_str mg_http_var(struct mg_str buf, struct mg_str name);
  • 获取未编码的HTTP变量
  • 参数:
    • buf – 一个url编码的字符串:HTTP请求体或查询字符串(HTTP request body or query string)
    • name – 获取的变量名字
  • 返回值:返回变量的值 或 返回一个空的字符串,表示没有找到
  • 示例:
    1
    2
    3
    // We have received a request to /my/uri?a=b&c=d%20
    // The hm->query points to "a=b&c=d%20"
    struct mg_str v = mg_http_var(hm->query, mg_str("c")); // v = "d%20"

mg_http_get_var()

  • int mg_http_get_var(const struct mg_str *var, const char *name, char *buf, int len);
  • 获取并解码HTTP 变量
  • 参数:
    • var – HTTP请求体(HTTP request body)
    • name – 变量名
    • buf – 写入解码变量的缓冲区(Buffer to write decoded variable)
    • len – 缓冲区大小
  • 返回值:解码变量的长度 或 0,负数表示错误
  • 示例:
    1
    2
    3
    4
    char buf[100] = "";
    mg_http_get_var(&hm->body, "key1", buf, sizeof(buf)) {
    ...
    }

mg_http_creds()

  • void mg_http_creds(struct mg_http_message *hm, char *user, size_t userlen, char *pass, size_t passlen);
  • 从请求获取身份验证证书,然后将它存储到user, userlen, pass, passlen缓冲区中。
  • 证书按以下顺序查找
    • 从HTTP header中的Authorization中:
      • 基本身份(Basic auth) ,填充到userpass
      • 持票人身份(Bearer auth),仅填充到pass
    • 从 cookie 的access_token中,填充pass
    • 从搜索字符串参数的?access_token=...,填充pass
  • 如果都没有,userpass都被设置为以NULL结尾的字符串
  • 参数:
    • hm – 需要查找证书的HTTP 消息
    • user – 接收用户名字的缓冲区
    • userlen – user缓冲区的大小
    • pass – 接收密码的缓冲区
    • passlen – pass缓冲区的大小
  • 返回值:空
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    char user[100], pass[100];
    mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass)); // "user" is now user name and "pass" is now password from request
    }
    }

mg_http_match_uri()

  • bool mg_http_match_uri(const struct mg_http_message *hm, const char *glob);
  • 检查在HTTP请求报文中,是否有和给定的glob字符串相匹配的字符串
  • 参数:
    • hm – 需要匹配检索的HTTP消息
    • glob – 匹配的字符串
  • 返回值:如果在HTTP请求报文中找到了匹配的字符串,返回 True 或者 返回 False表示未匹配到
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    if (mg_http_match_uri(hm, "/secret")) {
    mg_http_reply(c, 200, NULL, "Very big secret!");
    } else {
    mg_http_reply(c, 200, NULL, "hello world..");
    }
    }
    }

mg_http_bauth()

  • void mg_http_bauth(struct mg_connection *c, const char *user, const char *pass);
  • 将一个基本的Authorization header写入到输出缓冲区
  • 参数:
    • c – 使用的连接
    • user – 用户名
    • pass – 密码
  • 返回值:无
  • 示例:使用基本验证来创建Stripe订阅的用法示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    mg_printf(c, "POST /v1/subscriptions HTTP/1.1\r\n"
    "Host: api.stripe.com\r\n"
    "Transfer-Encoding: chunked\r\n");
    mg_http_bauth(c, stripe_private_key, NULL); // Add Basic auth header
    mg_printf(c, "%s", "\r\n"); // End HTTP headers

    mg_http_printf_chunk(c, "&customer=%s", customer_id); // Set customer
    mg_http_printf_chunk(c, "&items[0][price]=%s", price); // And price
    mg_http_printf_chunk(c, ""); // End request

struct mg_http_part

  • 声明:
    1
    2
    3
    4
    5
    6
    // Parameter for mg_http_next_multipart
    struct mg_http_part {
    struct mg_str name; // Form field name
    struct mg_str filename; // Filename for file uploads
    struct mg_str body; // Part contents
    };
  • 描述HTTP 多个消息(multipart message)中单个部分的结构体

mg_http_next_multipart()

  • size_t mg_http_next_multipart(struct mg_str body, size_t offset, struct mg_http_part *part);
  • 根据给定的offset,在body中解析multipart chunk。一个初始的offset应该为0.在提供的part中填充参数,可能为空。返回下一块的offsete,或者返回0表示没有其他块(chunks)
  • 参数:
    • body – 消息体(message body)
    • offset – 开始偏移量(start offset)
    • part – 指向需要填充的struct mg_http_part结构体
  • 返回值:返回下一块的offsete,或者返回0表示没有其他块(chunks)
  • 示例:
    1
    2
    3
    4
    5
    6
    struct mg_http_part part;
    size_t pos = 0;

    while ((pos = mg_http_next_multipart(body, pos, &part)) != 0) {
    // Use part
    }

mg_http_upload()

  • int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm, struct mg_fs *fs, const char *path, size_t max_size);
  • 这是一个助手实用程序功能,用于通过小块上传大型文件。将HTTP POST 数据追加到指定目录的文件中。文件名和文件偏移由查询字符串参数指定:POST /upload?name=firmware.bin&offset=2048 HTTP/1.1。如果偏移量为0,则将文件截断。客户的责任是将文件分为较小的块,并发送一系列由此功能处理的POST请求
  • 参数:
    • c – 一个连接
    • hm – 一个需要被解析的HTTP message
    • fs – 需要写文件的文件系统,例如:&mg_fs_posix
    • path – 一个文件名
    • max_size – 允许的文件大小的最大值
  • 返回值:写完后,返回文件的大小 或者 返回一个负数表示错误
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    if (mg_http_match_uri(hm, "/upload")) {
    mg_http_upload(c, hm, &mg_fs_posix, "/tmp/myfile.bin", 99999);
    } else {
    struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve
    mg_http_serve_dir(c, ev_data, &opts); // static content
    }
    }
    }

1.4 WebSocket API

struct mg_ws_message

  • 声明:
    1
    2
    3
    4
    struct mg_ws_message {
    struct mg_str data; // WebSocket message data
    uint8_t flags; // WebSocket message flags
    };
  • 该结构代表Websocket消息。这个flag元素对应于RFC 6455第5.2节中所述的第一个字节。(https://www.rfc-editor.org/rfc/rfc6455#section-5.2)

WebSockete message type:

  • 要从传入消息中提取消息类型,在结构体mg_ws_messageflag元素中检查四个LSBs
  • 可能存在的WebSocket消息类型:
    1
    2
    3
    4
    5
    6
    #define WEBSOCKET_OP_CONTINUE 0
    #define WEBSOCKET_OP_TEXT 1
    #define WEBSOCKET_OP_BINARY 2
    #define WEBSOCKET_OP_CLOSE 8
    #define WEBSOCKET_OP_PING 9
    #define WEBSOCKET_OP_PONG 10
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_WS_MSG) {
    struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
    msgtype = wm->flags & 0x0F;
    if (msgtype == WEBSOCKET_OP_BINARY) {
    // This is a binary data message
    } else if (msgtype == WEBSOCKET_OP_TEXT) {
    // This is a text data message
    }
    }
    }
  • 当调用mg_ws_send()ms_ws_printf()发送消息时,请使用RFC 6455第5.6节中所述的正确消息类型进行数据帧(https://www.rfc-editor.org/rfc/rfc6455#section-5.6)

mg_ws_connect()

  • struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fn_data, const char *fmt, ...);
  • 创建客户端Websocket连接。这个函数不能连接到对端,它仅仅分配需要的资源和启动连接进程。当对端真正连接好了,会向连接事件处理函数发送一个MG_EV_CONNECT事件
  • 参数:
    • mgr – 使用的事件管理结构体
    • url – 指定的远程URL。例如:http://google.com
    • fn – 一个事件处理函数
    • fn_data – 一个任意指针,当事件处理函数被调用时,它会被作为fn_data传递。这个指针作为c->fn_data存储在连接结构体中
  • 返回值:返回一个指向创建的连接; 返回NULL表示错误
  • 示例
    1
    2
    3
    struct mg_connection *c = mg_ws_connect(&mgr, "ws://test_ws_server.com:1000",
    handler, NULL, "%s", "Sec-WebSocket-Protocol: echo\r\n");
    if(c == NULL) fatal("Cannot create connection");

mg_ws_upgrade()

  • void mg_ws_upgrade(struct mg_connection *c, struct mg_http_message *, const char *fmt, ...);
  • 升级给定HTTP连接到Websocket。fmt是一个类似于printf()格式的字符串,用于额外的HTTP标头,返回给Websocket握手的客户端。如果不需要额外的标头,将fmt设置为空。
  • 参数:
    • c – 使用的连接
    • hm – HTTP消息
    • fmt – 类似于printf的格式字符串,用于附加HTTP标头或为null
  • 返回值:无
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    mg_ws_upgrade(c, hm, NULL); // Upgrade HTTP to WS
    }
    }

mg_ws_send()

  • size_t mg_ws_send(struct mg_connection *c, const void *buf, size_t len, int op);
  • 向WebSocket对端发送数据
  • 参数:
    • c – 使用的连接
    • buf – 需要发送的数据
    • len – 需要发送的数据大小
    • op – WebSocket消息类型,参见WebSocket message type
  • 返回值:返回发送的字节数
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_WS_OPEN) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    mg_ws_send(c, "opened", 6, WEBSOCKET_OP_BINARY); // Send "opened" to web socket connection
    }
    }

mg_ws_printf(), mg_ws_vprintf()

  • size_t mg_ws_printf(struct mg_connection *, int op, const char *fmt, ...);
  • size_t mg_ws_vprintf(struct mg_connection *, int op, const char *fmt, va_list *);
  • ms_ws_send()相同,但是使用printf()语义格式化数据
  • 参数:
    • c – 使用的连接
    • op – WebSocket消息类型,参见WebSocket message type
    • fmt – 使用printf()语义格式化的字符串
  • 返回值:返回发送的字节数
  • 示例
    • mg_ws_printf(c, WEBSOCKET_OP_TEXT, "Hello, %s!", "world");

mg_ws_wrap()

  • size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op)
  • 将输出缓冲区中的数据转换为Websocket格式。有用然后通过WebSocket实施协议。具体示例参见examples/mqtt-over-ws-client
  • 参数:
    • c – 使用的连接
    • len – 转换的字节数
    • op – WebSocket消息类型
  • 返回值:返回连接结构体中输出缓冲区新的大小
  • 示例
    1
    2
    3
    size_t len = c->send.len;         // Store output buffer len
    mg_mqtt_login(c, s_url, &opts); // Write MQTT login message
    mg_ws_wrap(c, c->send.len - len, WEBSOCKET_OP_BINARY); // Wrap it into WS

1.5 Timer API

mg_timer_add()

  • struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t period_ms, unsigned flags, void (*fn)(void *), void *fn_data);
  • 设置一个计时器。这是一个高级计时器API,允许将软件计时器添加到活动管理器。这个函数使用calloc()一个新的计时器,并将它添加到mgr->timers列表中。当调用mg_mgr_poll()时,所有添加的计时器均进行轮询,并在计时器到期时调用计时器设定的函数
  • 注意:
    • 确保计时器的间隔等于或大于mg_mgr_poll()的超时时间
  • 参数:
    • mgr – 指向事件管理器的结构体指针
    • ms – 一个时间间隔,以毫秒为单位
    • flags – 计时器标志掩码:MG_TIMER_REPEATMG_TIMER_RUN_NOW
    • fn – 函数调用
    • fn_data – 调用的函数参数
  • 返回值:返回一个指向创建的计时器的指针
  • 示例:
    1
    2
    3
    4
    5
    void timer_fn(void *data) {
    // ...
    }

    mg_timer_add(mgr, 1000, MG_TIMER_REPEAT, timer_fn, NULL);

struct mg_timer

  • 声明:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct mg_timer {
    uint64_t period_ms; // Timer period in milliseconds
    uint64_t expire; // Expiration timestamp in milliseconds
    unsigned flags; // Possible flags values below
    #define MG_TIMER_ONCE 0 // Call function once
    #define MG_TIMER_REPEAT 1 // Call function periodically
    #define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
    void (*fn)(void *); // Function to call
    void *arg; // Function argument
    struct mg_timer *next; // Linkage
    };
  • 计时器结构体。描述一个软件计时器。计时器粒度与主事件循环中的mg_mgr_poll()的超时参数相同

mg_timer_init()

  • void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t period_ms, unsigned flags, void (*fn)(void *), void *fn_data);
  • 设置一个计时器
  • 参数:
    • head – 指向mg_timer队列头部的指针
    • t – 指向一个需要被初始化的mg_timer
    • ms – 时间间隔,以毫秒为单位
    • flags – 计时器标志掩码:MG_TIMER_REPEATMG_TIMER_RUN_NOW
    • fn – 函数调用
    • fn_data – 调用的函数参数
  • 返回值:无
  • 示例:
    1
    2
    3
    4
    5
    6
    void timer_fn(void *data) {
    // ...
    }

    struct mg_timer timer, *head = NULL;
    mg_timer_init(&head, &timer, 1000, MG_TIMER_REPEAT, timer_fn, NULL);

mg_timer_free()

  • void mg_timer_free(struct mg_timer **head, struct mg_timer *t);
  • 释放计时器,将其从内部计时器列表中删除。
  • 参数:
    • head – 指向mg_timer队列头部的指针
    • t – 需要释放的计时器
  • 返回值:无
  • 示例:
    1
    2
    3
    struct mg_timer timer;
    // ...
    mg_timer_free(&timer);

mg_timer_poll()

  • void mg_timer_poll(struct mg_timer **head, uint64_t uptime_ms);
  • 如果当前的时间戳uptime_ms超过了计时器的到期时间,则计时器遍历列表,并调用它们
  • 参数:
    • head – 指向mg_timer列表头部的指针
    • uptime_ms – 当前时间戳
  • 返回值:无
  • 示例
    • mg_timer_poll(mg_millis());

1.6 Time

mg_millis()

  • int64_t mg_millis(void);
  • 以毫秒返回当前的正常运行时间。
  • 参数:无
  • 返回值:当前时间戳
  • 示例:
    • int64_t uptime = mg_millis();

1.7 String

struct mg_str

  • 声明:
    1
    2
    3
    4
    struct mg_str {
    const char *ptr; // Pointer to string data
    size_t len; // String len
    };
  • 该结构代表了任意内存的一部分,并不一定是zero-terminated。这是一个mongoose string,它在代码库中广泛使用,而不是C zero-terminated strings
  • 例如
    • 当一个HTTP request到达时,Mongoose创建了一个mg_http_message结构体,该结构体包含一个指向请求方法,URI,头部等struct mg_str结构体集合。这样,Mongoose避免了任何堆申请,并且不会修改接收的缓冲区。相反,它使用struct mg_str来描述HTTP请求的各个部分
    • 许多其他情况也是如此。
  • 注意:
    • 由于ptr不一定是zero-terminated,因此请勿使用libc字符串函数,例如:strlen()sscanf()

mg_str()

  • struct mg_str mg_str(const char *s)
  • NULL-terminated C-string创建一个Mongoose字符串。这个函数不重复提供字符串,并且将指针存储在创建的mg_str结构中
  • 注意:
    • 在C++(构造函数)中存在此问题,这个功能有同义词mg_str_s
  • 参数:
    • s – 一个指向需要存储到mg_str结构中的NULL-terminated string
  • 返回值:创建的Mongoose string
  • 示例:
    • struct mg_str str = mg_str("Hello, world!);

mg_str_n()

  • struct mg_str mg_str_n(const char *s, size_t n);
  • 从C-string(可以是non-NULL terminated,长度由n指定)创建Mongoose string。这个函数不重复提供字符串,并且将指针存储在创建的mg_str结构中
  • 参数:
    • s – 指向需要存储到创建的mg_str的字符串
    • n – 字符串长度
  • 返回值:创建的Mongoose string
  • 示例:
    • struct mg_str str = mg_str_n("hi", 2);

mg_casecmp()

  • int mg_casecmp(const char *s1, const char *s2);
  • 不区分大小写的,比较两个 NULL-terminated strings
  • 参数:
    • s1, s2 – 指向两个需要比较的字符串的指针
  • 返回值:
    • 如果两个字符串相等,则返回0
    • 如果第一个参数比第二个参数长,则返回大于0的数
    • 如果第一个参数比第二个参数短,则返回小于0的数
  • 示例:
    1
    2
    3
    if (mg_casecmp("hello", "HELLO") == 0) {
    // Strings are equal
    }

mg_ncasecmp()

  • int mg_ncasecmp(const char *s1, const char *s2, size_t len);
  • 不区分大小写的比较两个C-strings的前len个字符,或者遇到\0字符
  • 参数:
    • s1, s2 – 指向需要比较的两个字符串
    • len – 比较的最大长度
  • 返回值:
    • 如果两个字符串相等,则返回0
    • 如果第一个参数比第二个参数长,则返回大于0的数
    • 如果第一个参数比第二个参数短,则返回小于0的数
  • 示例:
    1
    2
    3
    if (mg_ncasecmp("hello1", "HELLO2", 5) == 0) {
    // Strings are equal
    }

mg_vcmp()

  • int mg_vcmp(const struct mg_str *s1, const char *s2);
  • 比较 mongoose string 和 C-string
  • 参数:
    • s1 – 指向需要比较的 mongoose string
    • s2 – 指向需要比较的 C-string
  • 返回值:
    • 如果两个字符串相等,则返回0
    • 如果第一个参数比第二个参数长,则返回大于0的数
    • 如果第一个参数比第二个参数短,则返回小于0的数
  • 示例:
    1
    2
    3
    4
    struct mg_str str = mg_str("hello");
    if (mg_vcmp(str, "hello") == 0) {
    // Strings are equal
    }

mg_vcasecmp()

  • int mg_vcasecmp(const struct mg_str *str1, const char *str2);
  • 不区分大小的比较 mongoose string 和 C-string
  • 参数:
    • s1 – 指向需要比较的 mongoose string
    • s2 – 指向需要比较的 C-string
  • 返回值:
    • 如果两个字符串相等,则返回0
    • 如果第一个参数比第二个参数长,则返回大于0的数
    • 如果第一个参数比第二个参数短,则返回小于0的数
  • 示例:
    1
    2
    3
    4
    struct mg_str str = mg_str("hello");
    if (mg_vcasecmp(str, "HELLO") == 0) {
    // Strings are equal
    }

mg_strcmp()

  • int mg_strcmp(const struct mg_str str1, const struct mg_str str2);
  • 比较两个 mongoose strings
  • 参数:
    • str1, str2 – 指向两个需要比较的 mongoose strings
  • 返回值:
    • 如果两个字符串相等,则返回0
    • 如果第一个参数比第二个参数长,则返回大于0的数
    • 如果第一个参数比第二个参数短,则返回小于0的数
  • 示例:
    1
    2
    3
    4
    5
    struct mg_str str1 = mg_str("hello");
    struct mg_str str2 = mg_str("hello");
    if (mg_strcmp(str1, str2) == 0) {
    // Strings are equal
    }

mg_strdup()

  • struct mg_str mg_strdup(const struct mg_str s);
  • 重复提供的字符串。返回一个新的字符串或者MG_NULL_STR表示错误。
  • 注意:
    • 这个函数为返回的字符串分配内存。需要使用free()函数释放
  • 参数:
    • s – 需要重复的 mongoose string
  • 返回值:重复的字符串
  • 示例:
    1
    2
    3
    4
    struct mg_str str1 = mg_str("hello");
    struct mg_str str2 = mg_strdup(str1);
    //...
    free((void *)str2.ptr);

mg_strstr()

  • const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle)
  • haystack字符串中查找needle子字符串
  • 参数:
    • haystack – 需要查找子字符串的 mongoose string
    • needle – 需要查找的 mongoose string
  • 返回值:
    • 返回一个指向neddlehaystack中发生的位置的指针
    • 失败,返回NULL
  • 示例:
    1
    2
    3
    4
    5
    6
    struct mg_str str = mg_str("Hello, world");
    struct mg_str sub_str = mg_str("world");

    if (mg_strstr(str, sub_str) != NULL) {
    // Found
    }

mg_strstrip()

  • struct mg_str mg_strstrip(struct mg_str s)
  • 删除 mongoose string s的头部和尾部的空格
  • 参数:
    • s – 需要修剪的 mongoose string
  • 返回值:输入的字符串
  • 示例:
    1
    2
    3
    4
    struct mg_str str = mg_strstrip(mg_str("   Hello, world   "));
    if (mg_vcmp(str, "Hello, world") == 0) {
    // Strings are equal
    }

mg_match()

  • bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str *caps);
  • 检查字符串str是否匹配pattern,可选地将通配符捕获到提供的数组caps
  • 注意:
    • 如果caps是非空的,那么caps数组的大小最小为pattern的长度加1.
    • 最后的 cap 将会被初始化成一个空的字符串
  • 全局匹配规则:
    • ? – 匹配任何单个字符
    • * – 匹配0个或多个字符,除了/
    • # – 匹配0个或多个字符
    • 任何其他字符只匹配它自身
  • 参数:
    • str – 需要匹配的字符串
    • patter – 与之匹配的规则(模式)
    • caps – 通配符符号的可选捕获数组?, *, #
  • 返回值:
    • 匹配成功,返回true
    • 其他情况,返回false
  • 示例:
    1
    2
    3
    4
    5
    // Assume that hm->uri holds /foo/bar. Then we can match the requested URI:
    struct mg_str caps[3]; // Two wildcard symbols '*' plus 1
    if (mg_match(hm->uri, mg_str("/*/*"), caps)) {
    // caps[0] holds `foo`, caps[1] holds `bar`.
    }

mg_commalist()

  • bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v);
  • 解析字符串S,这是一个分隔的条目列表。条目可以是任意字符串,该字符串存储在v中,或者分别存储在kv中的KEY=VALUE
  • 重要:
    • 此函数通过指向下一个条目来修改s
  • 参数:
    • s – 需要搜索条目的字符串
    • k – 一个指向mg_str的指针,接收条目键
    • v – 一个指向mg_str的指针,接收条目值
  • 返回值:
    • 如果条目被找到,返回true
    • 其他情况,返回false
  • 示例:
    1
    2
    3
    4
    struct mg_str k, v, s = mg_str("a=333,b=777");
    while (mg_commalist(&s, &k, &v)) // This loop output:
    printf("[%.*s] set to [%.*s]\n", // [a] set to [333]
    (int) k.len, k.ptr, (int) v.len, v.ptr); // [b] set to [777]

mg_hex()

  • char *mg_hex(const void *buf, size_t len, char *dst);
  • 十六进制编码的二进制数据buflen输入到一个缓冲区dst,并将其终止。这个输出缓冲区至少比2 x len + 1
  • 参数:
    • buf – 十六进制编码的数据
    • len – 数据长度
    • dst – 指向输出缓冲区的指针
  • 返回值:
    • 返回dst指针。这个编码的字符是小写的
  • 示例:
    1
    2
    3
    4
    5
    char data[] = "\x1\x2\x3";
    char buf[sizeof(data)*2];
    char *hex = mg_hex(data, sizeof(data) - 1, buf);
    LOG(LL_INFO, ("%s", hex)); // Output "010203";
    free(hex);

mg_unhex()

  • void mg_unhex(const char *buf, size_t len, unsigned char *to);
  • 十六进制字符串buflen输入到缓冲区to。这个缓冲区to必须大于lsn / 2
  • 参数:
    • buf – 需要十六进制解码的数据
    • len – 数据大小
    • to – 指向输出缓冲区的指针
  • 返回值:无
  • 示例:
    1
    2
    3
    4
    char data[] = "010203";
    char *buf[sizeof(data)/2];
    char *hex = mg_unhex(data, sizeof(data) - 1, buf); // buf is now [1,2,3]
    free(hex);

mg_unhexn()

  • unsigned long mg_unhexn(const char *s, size_t len);
  • 解析十六进制编码的字符串slen个字节。这个len最大值为long x 2的宽度,例如:32-bit platform it is 8
  • 参数:
    • s – 需要解析的字符串
    • len – 字符串长度
  • 返回值:返回解析的值
  • 示例:
    1
    2
    3
    char data[] = "010203";
    char *buf[sizeof(data)/2];
    unsigned long val = mg_unhex(data, sizeof(data) - 1); // val is now 123

mg_remove_double_dots()

  • char *mg_remove_double_dots(char *s);
  • 通过从中删除双点,修改字符串s。用于修改从网络收到的文件名或URI
  • 参数:
    • s – 需要修改的字符串
  • 返回值:返回s指针
  • 示例:
    1
    2
    char data[] = "../../a.txt";
    mg_remove_double_dots(data); // data is /a.txt

mg_snprintf(), mg_vsnprintf()

  • size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...);
  • size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap);
  • snprintf()标准函数一样,打印格式的字符串到字符串缓冲区中,但是以一种可预测的方式,不取决于C库或构建环境。返回值可以大于缓冲区长度len,在这种情况下,溢出字节未打印。Mongoose库通常用于以JSON格式交换数据因此,还支持非标准%q%v%h指定符用于格式化JSON字符串
  • 参数:
    • buf – 指向输出缓冲区的指针
    • len – 缓冲区大小
    • fmt – 类似于printf的格式字符串
  • 支持格式指定符
    • hhd, hd, d, ld, lld – 用于 char, short, int, long, int64_t
    • hhu, hu, u, lu, llu – 相同,但是用于无符号
    • hhx, hx, x, lx, llx – 相同,无符号并且以十六进制输出
    • s – 对应char *
    • q – 对应char *,输出JSON格式字符串(extension)
    • Q – 对应char *,输出双引号的JSON格式字符串(extension)
    • H – 对应int, void *, 输出双引号的十六进制字符串(extension)
    • I – 对应int(4 或 6), void *, 输出IP地址(extension)
    • A – 对应void *, 输出硬件地址(extension)
    • V – 对应int, void *, 输出双引号的base64 字符串(extension)
    • M – 对应mg_pfn_t,调用另一个输出函数(extension)
    • g, f – 对应double
    • c – 对应char
    • % – 对应%字符自己
    • p – 对应任何指针,输出0x....十六进制值
    • %X.Y – 可选宽度和精度修饰符
    • %.* – 可选的精度修饰符指定为int参数
  • 返回值:返回打印的字节数
  • 发送一个JSON HTTP response:
    • mg_http_reply(c, 200, "Content-Type: application/json\r\n", "{ %Q: %g}", "value", 1.2345);
  • 使用更复杂格式字符串的示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    mg_snprintf(buf, sizeof(buf), "%lld", (int64_t) 123);   // 123
    mg_snprintf(buf, sizeof(buf), "%.2s", "abcdef"); // ab
    mg_snprintf(buf, sizeof(buf), "%.*s", 2, "abcdef"); // ab
    mg_snprintf(buf, sizeof(buf), "%05x", 123); // 00123
    mg_snprintf(buf, sizeof(buf), "%%-%3s", "a"); // %- a
    mg_snprintf(buf, sizeof(buf), "hi, %Q", "a"); // hi, "a"
    mg_snprintf(buf, sizeof(buf), "r: %M, %d", f,1,2,7); // r: 3, 7
    mg_snprintf(buf, sizeof(buf), "%I", 4, "abcd"); // 97.98.99.100
    mg_snprintf(buf, sizeof(buf), "%A", "abcdef"); // 61:62:63:64:65:66

    // Printing sub-function for %M specifier. Grabs two int parameters
    size_t f(void (*out)(char, void *), void *ptr, va_list *ap) {
    int a = va_arg(*ap, int);
    int b = va_arg(*ap, int);
    return mg_xprintf(out, ptr, "%d", a + b);
    }

mg_mprintf(), mg_vmprintf()

  • char *mg_mprintf(const char *fmt, ...);
  • char *mg_vmprintf(const char *fmt, va_list *ap);
  • 将消息打印输出到分配的缓冲区中。调用者必须手动释放缓冲区
  • 参数:
    • fmt – 类似于printf的格式字符串
  • 返回值:分配的内存缓冲区
  • 示例:
    1
    2
    char *msg = mg_mprintf("Double quoted string: %Q!", "hi");
    free(msg);

mg_xprintf(), mg_vxprintf()

  • size_t mg_xprintf(void (*out)(char, void *), void *param, const char *fmt, ...);
  • size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt, va_list *ap);
  • 使用指定字符输出函数打印消息
  • 参数:
    • out – 被用于打印字符的函数
    • param – 被传给out的参数
    • fmt – 类似于printf的格式字符串
  • 返回值:返回打印的字节数
  • 示例:
    1
    2
    3
    void myfn(char c, void *p);

    size_t len = mg_xprintf(myfn, myfn_p, "Double quoted string: %Q!", "hi");

mg_pfn_iobuf()

  • void mg_pfn_iobuf(char ch, void *param);
  • 将一个字符打印到通用IO缓冲区 Generic IO buffer
  • 参数:
    • ch – 被打印的字节
    • param – 必须是struct mg_iobuf *
  • 示例:
    • mg_xprintf(mg_pfn_iobuf, &c->send, "hi!"); // Append to the output buffer

mg_to64()

  • int64_t mg_to64(struct mg_str str);
  • uint64_t mg_tou64(struct mg_str str);
  • 解析字符串持有的64位整数的值。
  • 参数:
    • str – 需要解析的字符串
  • 返回值:解析的值
  • 示例:
    • int64_t val = mg_to64(mg_str("123")); // Val is now 123

mg_aton()

  • bool mg_aton(struct mg_str str, struct mg_addr *addr);
  • 解析存储在str的IP地址,并将结果存储在addr
  • 参数:
    • str – 需要解析的字符串,例如:1.2.3.4, [::1], 01:02::03
    • addr – 指向接收解析结果的mg_addr字符串的指针
  • 返回值:
    • 成功,返回true
    • 其他情况,返回false
  • 示例:
    1
    2
    3
    4
    struct mg_addr addr;
    if (mg_aton(mg_str("127.0.0.1"), &addr)) {
    // addr is now binary representation of 127.0.0.1 IP address
    }

1.8 JSON API

  • 请注意,Mongoose的打印功能支持非标准格式指定Q和%m,它们可以轻松打印JSON字符串:
    • char *json = mg_mprintf("{ %Q:%d}", "value", 123); // {"value":123}
    • free(json);
  • 因此,对于完整的JSON支持,需要一组解析功能 - 如下所述。

mg_json_get()

  • enum { MG_JSON_TOO_DEEP = -1, MG_JSON_INVALID = -2, MG_JSON_NOT_FOUND = -3 };
  • int mg_json_get(struct mg_str json, const char *path, int *toklen);
  • 解析JSON字符串json,并且返回JSON path 指定的元素的偏移。这个元素的长度被存储在toklen
  • 参数:
    • json – 保存有一个有效JSON的字符串
    • path – 一个JSON 路径,必须由$开始,例如:$.user
    • toklen – 指向接收元素的长度的指针,可以为NULL
  • 返回值:
    • 返回元素的偏移量
    • 返回负数 MG_JSON_*表示错误
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // Create a json string: { "a": 1, "b": [2, 3] }
    char *buf = mg_mprintf("{ %Q: %d, %Q: [%d, %d] }", "a", 1, "b", 2, 3);
    struct mg_str json = mg_str(buf);
    int offset, length;

    // Lookup "$", which is the whole JSON. Can be used for validation
    offset = mg_json_get(json, "$", &length); // offset = 0, length = 23

    // Lookup attribute "a". Point to value "1"
    offset = mg_json_get(json, "$.a", &length); // offset = 7, length = 1

    // Lookup attribute "b". Point to array [2, 3]
    offset = mg_json_get(json, "$.b", &length); // offset = 15, length = 6

    // Lookup attribute "b[1]". Point to value "3"
    offset = mg_json_get(json, "$.b[1]", &length); // offset = 19, length = 1

    free(buf);

mg_json_get_num()

  • bool mg_json_get_num(struct mg_str json, const char *path, double *v);
  • 在JSON路径path,从json字符串获取数字值(double)。如果成功,返回true
  • 参数:
    • json – 保存有效JSON字符串
    • path – 一个JSON路径。必须以$开始
    • v – 一个对应于值的占位符
  • 返回值:
    • 成功,返回true
    • 失败,返回false
  • 示例:
    1
    2
    3
    double d = 0.0;
    mg_json_get_num(mg_str("[1,2,3]", "$[1]", &d)); // d contains 2
    mg_json_get_num(mg_str("{\"a\":1.23}", "$.a", &d)); // d contains 1.23

mg_json_get_bool()

  • bool mg_json_get_bool(struct mg_str json, const char *path, bool *v);
  • 在JSON路径path,从json字符串获取布尔值(bool)。如果成功,返回true
  • 参数:
    • json – 保存有效JSON字符串
    • path – 一个JSON路径。必须以$开始
    • v – 一个对应于值的占位符
  • 返回值:
    • 成功,返回true
    • 失败,返回false
  • 示例:
    1
    2
    3
    bool b = false;
    mg_json_get_bool(mg_str("[123]", "$[0]", &b)); // Error. b remains to be false
    mg_json_get_bool(mg_str("[true]", "$[0]", &b)); // b is true

mg_json_get_long()

  • long mg_json_get_long(struct mg_str json, const char *path, long default_val);
  • 在JSON路径path,从json字符串获取数字值(long)。
  • 参数:
    • json – 保存有效JSON字符串
    • path – 一个JSON路径。必须以$开始
    • v – 一个对应于值的占位符
  • 返回值:
    • 返回找到的值
    • 返回default_val
  • 示例:
    1
    2
    long a = mg_json_get_long(mg_str("[123]", "$a", -1));   // a = -1
    long b = mg_json_get_long(mg_str("[123]", "$[0]", -1)); // b = 123

mg_json_get_str()

  • char *mg_json_get_str(struct mg_str json, const char *path);
  • 在JSON路径path,从json字符串获取字符串值。如果找到,使用calloc()分配内存的字符串,没有转义的返回给调用者。调用者需要手动使用free()释放返回的字符串
  • 参数:
    • json – 保存有效JSON字符串
    • path – 一个JSON路径。必须以$开始
  • 返回值:
    • 成功,返回non-NULL
    • 失败,返回NULL
  • 示例:
    1
    2
    3
    struct mg_str json = mg_str("{\"a\": \"hi\"}");  // json = {"a": "hi"}
    char *str = mg_json_get_str(json, "$.a"); // str = "hi"
    free(str);

mg_json_get_hex()

  • char *mg_json_get_hex(struct mg_str json, const char *path, int *len);
  • 在JSON路径path,从json字符串获取十六进制编码的缓冲区。如果找到,使用calloc()分配内存的缓冲区,解码,并且返回给调用者。调用者需要手动调用free()释放返回的字符串。返回的缓冲区是 0-terminated
  • 参数:
    • json – 保存有效JSON字符串
    • path – 一个JSON路径。必须以$开始
    • len – 一个指向接收解码长度的指针。可以为NULL
  • 返回值:
    • 成功,返回non-NULL
    • 失败,返回NULL
  • 示例:
    1
    2
    3
    struct mg_str json = mg_str("{\"a\": \"6869\"}"); // json = {"a": "6869"}
    char *str = mg_json_get_hex(json, "$.a", NULL); // str = "hi"
    free(str);

mg_json_get_b64()

  • char *mg_json_get_b4(struct mg_str json, const char *path, int *len);
  • 在JSON路径path,从json字符串获取base64 编码的缓冲区。如果找到,使用calloc()申请内存的缓冲区,解码,并返回给调用者。调用者需要手动调用free()释放返回的字符串。返回的缓冲区是 0-terminated
  • 参数:
    • json – 保存有效JSON字符串
    • path – 一个JSON路径。必须以$开始
    • len – 一个指向接收解码长度的指针。可以为NULL
  • 返回值:
    • 成功,返回non-NULL
    • 失败,返回NULL
  • 示例:
    1
    2
    3
    struct mg_str json = mg_str("{\"a\": \"YWJj\"}"); // json = {"a": "YWJj"}
    char *str = mg_json_get_b64(json, "$.a", NULL); // str = "abc"
    free(str);

1.9 Utility API

2.0 URL API

2.1 Logging API

简介

  • mongoose 中http相关api笔记

struct mg_http_header

  • 简介:

    • 结构代表HTTP标头,像Content-Type: text/htmlContent-Type 是一个 Header name,text/html/是一个 Header value
  • 原型

    1
    2
    3
    4
    struct mg_http_header {
    struct mg_str name; // Header name
    struct mg_str value; // Header value
    };

struct mg_http_message

  • 简介:

    • 结构代表HTTP消息。
  • 原型

    1
    2
    3
    4
    5
    6
    struct mg_http_message {
    struct mg_str method, uri, query, proto; // Request/response line
    struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers
    struct mg_str body; // Body
    struct mg_str message; // Request line + headers + body
    };

mg_http_listen

  • 简介:

    • 创建HTTP侦听器。
  • 原型

    1
    struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fn_data);
  • 参数:

    • mgr : 一个事件管理结构体
    • url : 一个URL,指定监听的本地IP地址和端口。例如:http://0.0.0.0:8000
    • fn : 一个事件处理函数
    • fn_data : 一个任意指针,当事件处理函数被调用时,它会被作为fn_data传递。这个指针作为c->fn_data存储在连接结构体中
  • 返回值:

    • 成功,返回一个指向创建的连接指针
    • 失败,返回NULL
  • 示例

    1
    2
    struct mg_connection *c = mg_http_listen(&mgr, "0.0.0.0:8000", fn, arg);
    if (c == NULL) fatal_error("Cannot create listener");

mg_http_connect

  • 简介

    • 创建HTTP客户端连接。这个函数不能连接到对端,它仅仅分配需要的资源和启动连接进程。当对端真正连接好了,会向连接事件处理函数发送一个MG_EV_CONNECT事件
  • 原型:

    1
    struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url, mg_event_handler_t fn, void *fn_data);
  • 参数:

    • mgr : 一个事件管理结构体
    • url : 一个URL,指定监听的本地IP地址和端口。例如:http://0.0.0.0:8000
    • fn : 一个事件处理函数
    • fn_data : 一个任意指针,当事件处理函数被调用时,它会被作为fn_data传递。这个指针作为c->fn_data存储在连接结构体中
  • 返回值:

    • 成功,返回一个指向创建的连接指针
    • 失败,返回NULL
  • 示例

    1
    2
    struct mg_connection *c = mg_http_connect(&mgr, "http://google.com", fn, NULL);
    if (c == NULL) fatal_error("Cannot create connection");

mg_http_status

  • 简介:

    • 获取HTTP响应的状态代码。
  • 原型

    1
    int mg_http_status(const struct mg_http_message *hm);
  • 参数:

    • hm : 需要解析的HTTP响应
  • 返回值:

    • 返回状态码,例如:200表示成功

mg_http_get_request_len

  • 简介:

    • 获取请求的长度。请求的长度是直到HTTP头结束的字节数。它不包括HTTP请求体的长度
  • 原型

    1
    int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
  • 参数:

    • buf : 指向存放请求数据的缓冲区的指针
    • buf_len : 缓冲区大小
  • 返回值:

    • 成功,返回请求的长度
    • 0, 消息不完整
    • -1, 错误
  • 示例:

    1
    2
    const char *buf = "GET /test \n\nGET /foo\n\n";
    int req_len = mg_http_get_request_len(buf, strlen(buf)); // req_len == 12

mg_http_parse

  • 简介:

    • 解析请求报文字符串,并存入到mg_http_message结构体中
  • 原型:

    1
    int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm);
  • 参数:

    • s : 一个请求字符串
    • len : 请求字符串的长度
    • hm : 存储解析请求报文结果的结构体指针
  • 返回值:

    • 返回请求报文的长度
  • 示例

    1
    2
    3
    struct mg_http_message hm;
    const char *buf = "GET / HTTP/1.0\n\n";
    if (mg_http_parse(buf, strlen(buf), &hm) > 0) { /* success */ }

mg_http_printf_chunk

  • 简介:

    • 使用printf()语义,写一个块编码的块数据。(Write a chunk of data in chunked encoding format, using printf() semantic)
  • 原型:

    1
    void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...);
  • 参数:

    • c : 一个连接指针
    • fmt : 以printf()语义的字符串
  • 返回值:

  • 示例

    1
    mg_http_printf_chunk(c, "Hello, %s!", "world");

mg_http_write_chunk

  • 简介:

    • 写入一个块编码格式的块数据(Write a chunk of data in chunked encoding format.)
  • 原型

    1
    void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len);
  • 参数:

    • c : 一个连接指针
    • buf : 需要写入的数据
    • len : 写入数据的长度
  • 返回值:

  • 示例:

    1
    mg_http_write_chunk(c, "hi", 2);

mg_http_delete_chunk

  • 简介:

    • 从输入缓冲区中删除指定的块(chunk)
  • 原型:

    1
    void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm);
  • 参数:

    • c : 连接指针
    • hm : 需要删除的块(chunk)
  • 返回值:

  • 示例

    1
    2
    3
    4
    5
    6
    7
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_CHUNK) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    mg_http_delete_chunk(c, hm); // Remove received chunk
    }
    }

struct mg_http_serve_opts

  • 简介:

    • 传递给mg_http_serve_dir()mg_http_serve_file()的结构,该结构驱动了这两个函数的行为
  • 原型

    1
    2
    3
    4
    5
    6
    7
    8
    struct mg_http_serve_opts {
    const char *root_dir; // Web root directory, must be non-NULL
    const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
    const char *extra_headers; // Extra HTTP headers to add in responses
    const char *mime_types; // Extra mime types, ext1=type1,ext2=type2,..
    const char *page404; // Path to the 404 page, or NULL by default
    struct mg_fs *fs; // Filesystem implementation. Use NULL for POSIX
    };

mg_http_serve_dir

  • 简介:

    • 根据给定选项服务多个静态文件。文件也可以被压缩,包括目录索引。所有压缩文件都必须以.gz结尾,并且不得在没有扩展名的情况下存在具有相同名称的文件,否则将优先考虑
  • 原型:

    1
    void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, const struct mg_http_serve_opts *opts);
  • 参数:

    • c : 使用的连接
    • hm : 应该被服务的HTTP消息
    • opts : 服务选项。请注意,opts.root_dir可以选择接受额外的逗号分隔uri=path
  • 返回值:

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    struct mg_http_serve_opts opts;
    memset(&opts, 0, sizeof(opts));
    opts.root_dir = "/var/www,/conf=/etc"; // Serve /var/www. URIs starting with /conf are served from /etc
    mg_http_serve_dir(c, hm, &opts);
    }
    }

mg_http_serve_file

  • 简介:

    • 服务一个静态文件。如果不存在带有路径中指定的文件名的文件,则Mongoose尝试附加.gz;如果存在这样的文件,它将使用Content-Encoding: gzip header 去服务
  • 原型:

    1
    void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm, const char *path, struct mg_http_serve_opts *opts);
  • 参数:

    • c : 使用连接
    • hm : 需要服务的HTTP消息
    • path : 需要服务的文件路径
    • opts : 服务选项
  • 返回值:

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    struct mg_http_serve_opts opts = {
    .mime_types = "png=image/png",
    .extra_headers = "AA: bb\r\nCC: dd\r\n"
    };
    mg_http_serve_file(c, hm, "a.png", &opts);
    }
    }

mg_http_reply

  • 简介:

    • 通过使用printf()语义发送简单的HTTP响应。这个函数根据body_fmt格式化响应体(response body),然后自动追加到一个正确的Content-Length头(header)。额外的headers需要通过headers参数传递
  • 原型:

    1
    void mg_http_reply(struct mg_connection *c, int status_code, const char *headers, const char *body_fmt, ...);
  • 参数:

    • c : 一个连接
    • status_code : 一个HTTP响应状态码
    • headers : 额外的headers,默认为NULL,如果不是空,则必须以\r\n结尾
    • fmt : 使用printf语义,需要格式化成HTTP body的字符串
  • 返回值:

  • 示例:

    1
    2
    3
    4
    5
    6
    // 发送一个简单的JSON响应:
    mg_http_reply(c, 200, "Content-Type: application/json\r\n", "{\"result\": %d}", 123);
    // 发送一个302重定向:
    mg_http_reply(c, 302, "Location: /\r\n", "");
    // 发送一个错误
    mg_http_reply(c, 403, "", "%s", "Not Authorized\n");

mg_http_get_header

  • 简介:

    • 获取HTTP header值
  • 原型:

    1
    struct mg_str *mg_http_get_header(struct mg_http_message *hm, const char *name);
  • 参数:

    • hm : 需要寻找 header 的HTTP消息
    • name : Header name
  • 返回值:

    • 成功,HTTP header
    • 失败,NULL
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Mongoose event handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    struct mg_str *s = mg_http_get_header(hm, "X-Extra-Header");
    if (s != NULL) {
    mg_http_reply(c, 200, "", "Holly molly! Header value: %.*s", (int) s->len, s->ptr);
    } else {
    mg_http_reply(c, 200, "", "Oh no, header is not set...");
    }
    }
    }

mg_http_get_header_var

  • 简介:

    • 解析具有表格name1=value1; name=value2;...的HTTP header,并获取一个给定的变量
  • 原型:

    1
    struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
  • 参数:

    • s : HTTP header
    • name : 变量名字
  • 返回值:

    • 成功,一个请求的变量
    • 失败,一个空的字符串
  • 示例:

    1
    2
    3
    4
    5
    6
    struct mg_str *cookie = mg_http_get_header(hm, "Cookie");
    struct mg_str token = mg_str("");

    if (cookie != NULL) {
    token = mg_http_get_header_var(*cookie, mg_str("access_token"));
    }

mg_http_var

  • 简介:

    • 获取未编码的HTTP变量
  • 原型:

    1
    struct mg_str mg_http_var(struct mg_str buf, struct mg_str name);
  • 参数:

    • buf : 一个url编码的字符串:HTTP请求体或查询字符串(HTTP request body or query string)
    • name : 获取的变量名字
  • 返回值:

    • 成功,返回变量的值
    • 失败,返回一个空字符串
  • 示例:

    1
    2
    3
    // We have received a request to /my/uri?a=b&c=d%20
    // The hm->query points to "a=b&c=d%20"
    struct mg_str v = mg_http_var(hm->query, mg_str("c")); // v = "d%20"

mg_http_get_var

  • 简介:

    • 获取并解码HTTP 变量
  • 原型:

    1
    int mg_http_get_var(const struct mg_str *var, const char *name, char *buf, int len);
  • 参数:

    • var : HTTP请求体(HTTP request body)
    • name : 变量名
    • buf : 写入解码变量的缓冲区(Buffer to write decoded variable)
    • len : 缓冲区大小
  • 返回值:

    • 成功,解码变量的长度, 0
    • 失败,返回负数
  • 示例:

    1
    2
    3
    4
    char buf[100] = "";
    mg_http_get_var(&hm->body, "key1", buf, sizeof(buf)) {
    ...
    }

mg_http_creds

  • 简介:

    • 从请求获取身份验证证书,然后将它存储到user, userlen, pass, passlen缓冲区中。
  • 原型:

    1
    void mg_http_creds(struct mg_http_message *hm, char *user, size_t userlen, char *pass, size_t passlen);
  • 参数:

    • hm : 需要查找证书的HTTP 消息
    • user : 接收用户名字的缓冲区
    • userlen : user缓冲区的大小
    • pass : 接收密码的缓冲区
    • passlen : pass缓冲区的大小
  • 返回值:

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    char user[100], pass[100];
    mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass)); // "user" is now user name and "pass" is now password from request
    }
    }

mg_http_match_uri

  • 简介:

    • 检查在HTTP请求报文中,是否有和给定的glob字符串相匹配的字符串
  • 原型:

    1
    bool mg_http_match_uri(const struct mg_http_message *hm, const char *glob);
  • 参数:

    • hm : 需要匹配检索的HTTP消息
    • glob : 匹配的字符串
  • 返回值:

    • 成功,true
    • 失败,false
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    if (mg_http_match_uri(hm, "/secret")) {
    mg_http_reply(c, 200, NULL, "Very big secret!");
    } else {
    mg_http_reply(c, 200, NULL, "hello world..");
    }
    }
    }

mg_http_bauth

  • 简介:

    • 将一个基本的Authorization header写入到输出缓冲区
  • 原型:

    1
    void mg_http_bauth(struct mg_connection *c, const char *user, const char *pass);
  • 参数:

    • c : 使用的连接
    • user : 用户名
    • pass : 密码
  • 返回值:

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    mg_printf(c, "POST /v1/subscriptions HTTP/1.1\r\n"
    "Host: api.stripe.com\r\n"
    "Transfer-Encoding: chunked\r\n");
    mg_http_bauth(c, stripe_private_key, NULL); // Add Basic auth header
    mg_printf(c, "%s", "\r\n"); // End HTTP headers

    mg_http_printf_chunk(c, "&customer=%s", customer_id); // Set customer
    mg_http_printf_chunk(c, "&items[0][price]=%s", price); // And price
    mg_http_printf_chunk(c, ""); // End request

struct mg_http_part

  • 简介:

    • 描述HTTP 多个消息(multipart message)中单个部分的结构体
  • 原型:

    1
    2
    3
    4
    5
    6
    // Parameter for mg_http_next_multipart
    struct mg_http_part {
    struct mg_str name; // Form field name
    struct mg_str filename; // Filename for file uploads
    struct mg_str body; // Part contents
    };

mg_http_next_multipart

  • 简介:

    • 根据给定的offset,在body中解析multipart chunk。一个初始的offset应该为0.在提供的part中填充参数,可能为空。返回下一块的offsete,或者返回0表示没有其他块(chunks)
  • 原型:

    1
    size_t mg_http_next_multipart(struct mg_str body, size_t offset, struct mg_http_part *part);
  • 参数:

    • body : 消息体
    • offset : 开始偏移量
    • part : 指向需要填充的struct mg_http_part结构体
  • 返回值:

    • 成功,返回下一块的offset
    • 失败,返回0,或者表示没有其他块
  • 示例:

    1
    2
    3
    4
    5
    6
    struct mg_http_part part;
    size_t pos = 0;

    while ((pos = mg_http_next_multipart(body, pos, &part)) != 0) {
    // Use part
    }

mg_http_upload

  • 简介:

    • 这是一个助手实用程序功能,用于通过小块上传大型文件。将HTTP POST 数据追加到指定目录的文件中。文件名和文件偏移由查询字符串参数指定:POST /upload?name=firmware.bin&offset=2048 HTTP/1.1。如果偏移量为0,则将文件截断。客户的责任是将文件分为较小的块,并发送一系列由此功能处理的POST请求
  • 原型:

    1
    int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm, struct mg_fs *fs, const char *path, size_t max_size);
  • 参数:

    • c : 一个连接
    • hm : 一个需要被解析的HTTP message
    • fs : 需要写文件的文件系统,例如:&mg_fs_posix
    • path : 一个文件名
    • max_size : 允许的文件大小的最大值
  • 返回值:

    • 成功,返回文件的大小
    • 失败,返回一个负数
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    if (mg_http_match_uri(hm, "/upload")) {
    mg_http_upload(c, hm, &mg_fs_posix, "/tmp/myfile.bin", 99999);
    } else {
    struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve
    mg_http_serve_dir(c, ev_data, &opts); // static content
    }
    }
    }

简介

  • mongoose的出站入站缓冲区接口
  • IO缓冲区由结构mg_iobuf描述,是一个简单的数据结构,可以在任意偏移量插入或删除数据块,并自动增长/收缩。

struct mg_iobuf

  • 简介:

    • 通用IO缓冲区。size指定buf指向的数据的分配大小,len指定当前存储的字节数。
  • 原型:

    1
    2
    3
    4
    5
    6
    struct mg_iobuf {
    unsigned char *buf; // Pointer to stored data
    size_t size; // Total size available
    size_t len; // Current number of bytes
    size_t align; // Alignment during allocation
    };

mg_iobuf_init

  • 简介:

    • 初始化IO缓冲区,分配字节大小
  • 原型:

    1
    int mg_iobuf_init(struct mg_iobuf *io, size_t size, size_t align);
  • 参数:

    • io – 要初始化的mg_iobuf结构的指针
    • size – 分配的字节数
    • align – 将大小对齐到对齐内存边界。0表示不对齐
  • 返回值:

    • 1 – 成功
    • 0 – 失败
  • 示例:

    1
    2
    3
    4
    struct mg_iobuf io;
    if (mg_iobuf_init(&io, 0, 64)) {
    // io successfully initialized
    }

mg_iobuf_resize

  • 简介:

    • 调整IO缓冲区的大小,将新的大小设置为size。在此之后,io->buf指针可能会发生变化,例如缓冲区变大。如果size为0,则释放io->buf并将其设置为NULL,同时将size和len都设置为0。 得到的io->size总是与io->align字节边界对齐;因此,为了避免内存碎片和频繁的重新分配,将io->align设置为更高的值。
  • 原型:

    1
    int mg_iobuf_resize(struct mg_iobuf *io, size_t size);
  • 参数:

    • io – 需要调整大小的iobuf
    • size – 新的大小
  • 返回值:

    • 1 – 成功
    • 0 – 失败
  • 示例:

    1
    2
    3
    4
    5
    6
    struct mg_iobuf io;
    mg_iobuf_init(&io, 0, 10); // An empty buffer with 10-byte alignment

    if (mg_iobuf_resize(&io, 1)) {
    // New io size is 10
    }

mg_iobuf_free

  • 简介:

    • 释放io->buf指向的内存并设置为NULL。size和len都被设置为0。
  • 原型:

    1
    void mg_iobuf_free(struct mg_iobuf *io);
  • 参数:

    • io – 需要释放的iobuf
  • 返回值:

  • 示例:

    1
    2
    3
    4
    5
    6
    struct mg_iobuf io;
    // IO buffer initialization
    // ...

    // Time to cleanup
    mg_iobuf_free(&io);

mg_iobuf_add

  • 简介:

    • 在偏移量处插入数据缓冲区buf、len。如果需要,iobuf将被扩展。产生的io->size总是与io->align字节边界对齐;因此,为了避免内存碎片和频繁的重新分配,将align设置为一个较大的值。
  • 原型:

    1
    size_t mg_iobuf_add(struct mg_iobuf *io, size_t offset, const void *buf, size_t len);
  • 参数:

    • io – 需要追加数据的iobuf
    • offset – 追加数据的偏移
    • buf – 追加的数据
    • len – 追加数据的长度
  • 返回值:

    • 更新后iobuf的长度
  • 示例:

    1
    2
    3
    struct mg_iobuf io;         // Declare buffer
    mg_iobuf_init(&io, 0, 16); // Initialise empty buffer with 16 byte alignment
    mg_iobuf_add(&io, io.len, "hello", 5); // Append "hello"

mg_iobuf_del

  • 简介:

    • 删除从偏移量开始的len字节,并移动剩余的字节。如果len大于io->len,则不会发生任何操作,因此这种调用会被忽略。
  • 原型:

    1
    size_t mg_iobuf_del(struct mg_iobuf *io, size_t offset, size_t len);
  • 参数:

    • io – 需要删除数据的iobuf
    • offset – 开始位置的偏移量
    • len – 删除的字节数
  • 返回值:

    • 更新后iobuf的长度
  • 示例:

    1
    2
    3
    4
    struct mg_iobuf io;
    mg_iobuf_init(&io, 0, 16); // Empty buffer, 16-bytes aligned
    mg_iobuf_add(&io, 0, "hello", 2); // io->len is 5, io->size is 16
    mg_iobuf_del(&io, 1, 3); // io->len is 2, io->size is still 16

简介

  • mongoose 日志相关函数
  • Mongoose为日志记录提供了一系列函数和宏。应用程序可以为自己的目的使用这些函数,也可以使用Mongoose API的其他部分。

LOG

  • 简介:

    • 日志宏
  • 原型:

    1
    2
    3
    4
    5
    #define LOG(level, args)
    #define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
    #define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
    #define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
    #define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  • 示例:

    1
    MG_INFO(("Hello %s!", "world"));  // Output "Hello, world"

mg_log_set

  • 简介:

    • 设置Mongoose日志级别
  • 原型:

    1
    void mg_log_set(const char *spec);
  • 参数:

    • spec – 字符串,包含日志级别,可以是以下值之一
      • 0 – 关闭日志
      • 1 – 仅输出错误
      • 2 – 输出错误和消息
      • 3 – 输出错误,消息和调试消息
      • 4 – 输出所有日志信息
  • 返回值:

  • 详解:

    • 可以根据源文件覆盖日志级别。例如,如果有一个名为foo.c的文件,您希望将全局级别设置为2(info),但将foo.c文件的日志级别提高到debug,那么规格应该是 “2,foo.c=3”。可以有多个以逗号分隔的重写。
  • 示例:

    1
    2
    mg_log_set("2");                  // Set log level to info
    mg_log_set("2,foo.c=3,bar.c=0"); // Set log level to info, with overrides

mg_hexdump

  • 简介:

    • 记录二进制数据buf, len的十六进制转储。
  • 原型:

    1
    void mg_hexdump(const void *buf, int len);
  • 参数:

    • buf – 数据指针
    • len – 数据大小
  • 返回值:

  • 示例:

    1
    mg_hexdump(c->recv.buf, c->recv.len);  // Hex dump incoming data

mg_log_set_fn

  • 简介:

    • 将日志重定向到自定义函数。
  • 原型:

    1
    void mg_log_set_fn(mg_pfn_t logfunc, void *param);
  • 参数:

    • logfunc – 记录单个字符的函数指针
    • param – 日志函数参数
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    static void mylog(char ch, void *param) {
    static char buf[256];
    static size_t len;
    buf[len++] = ch;
    if (ch == '\n' || len >= sizeof(buf)) {
    syslog(LOG_INFO, "%.*s", (int) len, buf); // Send logs
    len = 0;
    }
    }
    ...
    mg_log_set_fn(mylog, NULL);

简介

  • RPC(Remote Procedure Call, 远程过程调用),是一种通信协议和编程模型,用于实现分布式系统中不同节点之间的远程调用。它允许在不同计算机或进程之间像调用本地函数一样调用远程函数,隐藏了底层网络通信的细节
  • Mongoose包含一组函数,通过RPC方法简化服务器端处理。

struct mg_rpc

  • 简介:

    • RPC方法处理程序结构。每个方法在一个链表中都有一个入口,每个入口指向一个字符串,该字符串描述了将调用该方法的模式,以及为满足该方法调用而调用的函数,并带有一个适当的函数参数。
  • 原型:

    1
    2
    3
    4
    5
    6
    struct mg_rpc {
    struct mg_rpc *next; // Next in list
    struct mg_str method; // Method pattern
    void (*fn)(struct mg_rpc_req *); // Handler function
    void *fn_data; // Handler function argument
    };

struct mg_rpc_req

  • 简介:

    • RPC请求描述符。被调用的方法会收到一个包含请求的描述符,以及一个指向函数的指针,该函数将被调用来打印输出响应,并带有一个适当的函数参数;例如:mg_pfn_realloc() 或 mg_pfn_iobuf()
  • 原型:

    1
    2
    3
    4
    5
    6
    7
    8
    struct mg_rpc_req {
    struct mg_rpc **head; // RPC handlers list head
    struct mg_rpc *rpc; // RPC handler being called
    mg_pfn_t pfn; // Response printing function
    void *pfn_data; // Response printing function data
    void *req_data; // Arbitrary request data
    struct mg_str frame; // Request, e.g. {"id":1,"method":"add","params":[1,2]}
    };

mg_rpc_add

  • 简介:

    • 将方法method_pattern添加到RPC方法列表的头部。调用该方法将调用handler,并将handler_data与请求一起传递给它(如下使用示例中的r->fn_data)。
  • 原型:

    1
    2
    void mg_rpc_add(struct mg_rpc **head, struct mg_str method_pattern,
    void (*handler)(struct mg_rpc_req *), void *handler_data);
  • 参数:

    • head – 链表指针
    • method_pattern – 方法的名称
    • handler – 执行该方法操作的RPC函数
    • handler_data – 任意函数数据
  • 注:

    • 如果method_pattern为空字符串,该处理程序将被调用来处理JSON-RPC响应。如果JSON请求是由双方发起的,那么处理响应可能是必要的。
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    struct mg_rpc *s_rpc_head = NULL;

    static void rpc_sum(struct mg_rpc_req *r) {
    double a = 0.0, b = 0.0;
    mg_json_get_num(r->frame, "$.params[0]", &a);
    mg_json_get_num(r->frame, "$.params[1]", &b);
    mg_rpc_ok(r, "%g", a + b);
    }

    static void rpc_mul(struct mg_rpc_req *r) {//...}
    }

    mg_rpc_add(&s_rpc_head, mg_str("sum"), rpc_sum, NULL);
    mg_rpc_add(&s_rpc_head, mg_str("mul"), rpc_mul, NULL);

mg_rpc_del

  • 简介:

    • 从RPC方法列表中删除带有RPC函数处理程序的方法
  • 原型:

    1
    void mg_rpc_del(struct mg_rpc **head, void (*handler)(struct mg_rpc_req *));
  • 参数:

    • head – 链表指针
    • handler – RPC函数处理程序的方法,使用NULL删除全部
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    struct mg_rpc *s_rpc_head = NULL;
    // add methods
    // ...

    // Time to cleanup
    mg_rpc_del(&s_rpc_head, rpc_mul); // Deallocate specific handler
    mg_rpc_del(&s_rpc_head, NULL); // Deallocate all RPC handlers

mg_rpc_process

  • 简介:

    • 为这个请求调用合适的方法。如果请求的方法不存在,将调用mg_rpc_err()并打印错误提示。
  • 原型:

    1
    void mg_rpc_process(struct mg_rpc_req *req);
  • 参数:

    • req – 一个请求
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    struct mg_rpc *s_rpcs = NULL;                               // Empty RPC list head
    mg_rpc_add(&s_rpcs, mg_str("rpc.list"), mg_rpc_list, NULL); // Add rpc.list
    // ... add more RPC methods

    // On request, process the incoming frame
    struct mg_str req = mg_str("{\"id\":1,\"method\":\"sum\",\"params\":[1,2]}");
    struct mg_iobuf io = {0, 0, 0, 512}; // Empty IO buf, with 512 realloc granularity
    struct mg_rpc_req r = {
    .head = &s_rpcs, // RPC list head
    .rpc = NULL, // This will be set by mg_rpc_process()
    .pfn = mg_pfn_iobuf, // Printing function: print into the io buffer
    .pfn_data = &io, // Pass our io buffer as a parameter
    .req_data = NULL, // No specific request data
    .frame = req, // Specify incoming frame
    };

    mg_rpc_process(&r);
    if (io.buf != NULL) printf("Response: %s\n", (char *) io.buf);
    mg_iobuf_free(&io);

mg_rpc_ok, mg_rpc_vok

  • 简介:

    • 打印结果帧的辅助函数
  • 原型:

    1
    2
    void mg_rpc_ok(struct mg_rpc_req *, const char *fmt, ...);
    void mg_rpc_vok(struct mg_rpc_req *, const char *fmt, va_list *ap);
  • 参数:

    • req – 一个请求
    • fmt – 使用printf语义格式化的字符串
  • 示例:

    1
    2
    3
    4
    5
    6
    static void rpc_sum(struct mg_rpc_req *r) {
    double a = 0.0, b = 0.0;
    mg_json_get_num(r->frame, "$.params[0]", &a);
    mg_json_get_num(r->frame, "$.params[1]", &b);
    mg_rpc_ok(r, "%g", a + b);
    }

mg_rpc_err, mg_rpc_verr

  • 简介:

    • 打印错误帧的辅助函数
  • 原型:

    1
    2
    void mg_rpc_err(struct mg_rpc_req *, int code, const char *fmt, ...);
    void mg_rpc_verr(struct mg_rpc_req *, int code, const char *fmt, va_list *);
  • 参数:

    • req – 一个请求
    • fmt – 使用printf语义格式化的字符串
  • 示例:

    1
    2
    3
    4
    static void rpc_dosome(struct mg_rpc_req *r) {
    ...
    mg_rpc_err(r, -32109, "\"%.*s not found\"", len, &r->frame.ptr[offset]);
    }

mg_rpc_list

  • 简介:

    • 内置RPC方法,用于列出所有已注册的RPC方法。该函数通常不直接调用,而是作为方法注册。
  • 原型:

    1
    void mg_rpc_list(struct mg_rpc_req *r);
  • 参数:

    • req – 一个请求
  • 示例:

    1
    mg_rpc_add(&s_rpc_head, mg_str("rpc.list"), mg_rpc_list, &s_rpc_head);

简介

  • SNTP server(simple network time protocol), 是一种用于提供时间同步服务的网络服务器。它基于网络通信协议,允许计算机和其他网络设备通过网络获取准确的时间信息

mg_sntp_connect

  • 简介:

    • 连接SNTP服务器。
  • 原型:

    1
    2
    struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
    mg_event_handler_t fn, void *fn_data)
  • 参数:

    • mgr – 使用的事件管理器
    • url – 指定远程URL,如果为空,则为time.google.com。
    • fn – 事件处理函数
    • fn_data – 一个任意指针,在调用事件处理程序时作为fn_data传递。该指针也将作为c->fn_data存储在连接结构中。
  • 返回值:

    • 成功,返回指向创建的连接的指针
    • 失败,返回NULL
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
    if (ev == MG_EV_SNTP_TIME) {
    // Time received
    struct timeval *tv = (struct timeval *tv)evd;
    }
    }
    ...
    mg_sntp_connect(mgr&, NULL /* connect to time.google.com */, sntp_cb, NULL);

mg_sntp_request

  • 简介:

    • 向SNTP服务器发送时间请求
  • 原型:

    1
    void mg_sntp_request(struct mg_connection *c)
  • 参数:

    • c – 使用的连接
  • 返回值:

  • 示例:

    1
    mg_sntp_request(c);

简介

  • mongoose工具的计时器相关笔记

struct mg_timer

  • 简介:

    • 计时器结构体。描述一个软件计时器。计时器粒度与主事件循环中的mg_mgr_poll()的超时参数相同
  • 原型:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct mg_timer {
    uint64_t period_ms; // Timer period in milliseconds
    uint64_t expire; // Expiration timestamp in milliseconds
    unsigned flags; // Possible flags values below
    #define MG_TIMER_ONCE 0 // Call function once
    #define MG_TIMER_REPEAT 1 // Call function periodically
    #define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
    void (*fn)(void *); // Function to call
    void *arg; // Function argument
    struct mg_timer *next; // Linkage
    };

mg_timer_add

  • 简介:

    • 设置一个计时器。这是一个高级计时器API,允许将软件计时器添加到活动管理器。
    • 这个函数使用calloc()一个新的计时器,并将它添加到mgr->timers列表中。
    • 当调用mg_mgr_poll()时,所有添加的计时器均进行轮询,并在计时器到期时调用计时器设定的函数
  • 原型:

    1
    struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t period_ms, unsigned flags, void (*fn)(void *), void *fn_data);
  • 参数:

    • mgr – 指向事件管理器的结构体指针
    • ms – 一个时间间隔,以毫秒为单位
    • flags – 计时器标志掩码:MG_TIMER_REPEATMG_TIMER_RUN_NOW
    • fn – 函数调用
    • fn_data – 调用的函数参数
  • 返回值:

    • 返回一个指向创建的计时器的指针
  • 详解:

    • 确保计时器的间隔等于或大于mg_mgr_poll()的超时时间
  • 示例:

    1
    2
    3
    4
    5
    void timer_fn(void *data) {
    // ...
    }

    mg_timer_add(mgr, 1000, MG_TIMER_REPEAT, timer_fn, NULL);

mg_timer_init

  • 简介:

    • 设置一个计时器
  • 原型:

    1
    void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t period_ms, unsigned flags, void (*fn)(void *), void *fn_data);
  • 参数:

    • head – 指向mg_timer队列头部的指针
    • t – 指向一个需要被初始化的mg_timer
    • ms – 时间间隔,以毫秒为单位
    • flags – 计时器标志掩码:MG_TIMER_REPEATMG_TIMER_RUN_NOW
    • fn – 函数调用
    • fn_data – 调用的函数参数
  • 返回值:

  • 示例

    1
    2
    3
    4
    5
    6
    void timer_fn(void *data) {
    // ...
    }

    struct mg_timer timer, *head = NULL;
    mg_timer_init(&head, &timer, 1000, MG_TIMER_REPEAT, timer_fn, NULL);

mg_timer_free

  • 简介:

    • 释放计时器,将其从内部计时器列表中删除。
  • 原型:

    1
    void mg_timer_free(struct mg_timer **head, struct mg_timer *t);
  • 参数:

    • head – 指向mg_timer队列头部的指针
    • t – 需要释放的计时器
  • 返回值:

  • 示例:

    1
    2
    3
    struct mg_timer timer;
    // ...
    mg_timer_free(&timer);

mg_timer_poll

  • 简介:

    • 如果当前的时间戳uptime_ms超过了计时器的到期时间,则计时器遍历列表,并调用它们
  • 原型:

    1
    void mg_timer_poll(struct mg_timer **head, uint64_t uptime_ms);
  • 参数:

    • head – 指向mg_timer列表头部的指针
    • uptime_ms – 当前时间戳
  • 返回值:

  • 示例:

    1
    mg_timer_poll(mg_millis());

mg_millis

  • 简介:

    • 以毫秒为单位返回当前运行时间。
  • 原型:

    1
    int64_t mg_millis(void);
  • 参数:

  • 返回值:

    • 当前时间
  • 示例:

    1
    int64_t uptime = mg_millis();

简介

  • TLS(Transport Layer Security),是一种用于保护网络通信安全性的加密协议。它建立在传输层协议(例如TCP)之上,用于在客户端和服务器之间创建安全的通信通道

struct mg_tls_opts

  • 简介:

    • TLS初始化结构
  • 原型:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct mg_tls_opts {
    const char *ca; // CA certificate file. For both listeners and clients
    const char *crl; // Certificate Revocation List. For clients
    const char *cert; // Certificate
    const char *certkey; // Certificate key
    const char *ciphers; // Cipher list
    struct mg_str srvname; // If not empty, enables server name verification
    struct mg_fs *fs; // FS API for reading certificate files
    };
  • 参数:

    • ca – 证书颁发机构。可以是文件名或字符串。用于验证另一端发送给我们的证书。如果为空,则禁用证书检查。
    • crl – 证书吊销列表。可以是文件名或字符串。用于验证另一端发送给我们的证书。如果为空,则禁用证书吊销检查。
    • cert – 我们自己的证书。可以是文件名或字符串。如果为NULL,则不与对方进行认证。
    • certkey – 证书的密钥。有时,证书和它的密钥绑定在一个.pem文件中,在这种情况下,cert和certkey的值可能是相同的
    • ciphers – 允许使用的密码列表
    • srvname – 启用服务器名称验证
  • 注:

    • 如果ca和cert都设置了,那么所谓的双向TLS就启用了,这时双方都要互相验证。通常,服务器端连接同时设置ca和cert,而客户端只设置ca。

mg_tls_init

  • 简介:

    • 在给定连接上初始化TLS
  • 原型:

    1
    void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts);
  • 参数:

    • c – 需要初始化TLS的连接
    • opts – TLS初始化参数
  • 返回值:

  • 示例:

    1
    2
    struct mg_tls_opts opts = {.cert = "ca.pem"};
    mg_tls_init(c, &opts);
  • 注:

    • mbedTLS使用mg_random作为RNG。mg_random可以通过设置MG_ENABLE_CUSTOM_RANDOM=1并定义自己的mg_random()实现来覆盖。

简介

  • mongoose关于URL的函数

mg_url_port

  • 简介:

    • 根据给定的URL返回端口
  • 原型:

    1
    unsigned short mg_url_port(const char *url);
  • 参数:

    • url – 需要提取端口号的URL
  • 返回值:

    • 成功,返回给定URL的端口号
    • 失败,如果URL不包含端口并且URL协议没有默认端口,则为0
  • 示例:

    1
    2
    unsigned short port1 = mg_url_port("https://myhost.com") // port1 is now 443 (default https port)
    unsigned short port2 = mg_url_port("127.0.0.1:567") // port2 is now 567

mg_url_is_ssl

  • 简介:

    • 检查给定的URL是否使用加密方案
  • 原型:

    1
    int mg_url_is_ssl(const char *url);
  • 参数:

    • url – 需要检查的URL
  • 返回值:

    • 如果URL使用了加密方案,返回0
    • 如果没有,则返回非0
  • 示例:

    1
    2
    3
    if (mg_url_is_ssl("https://example.org") == 0) {
    // scheme is encrypted
    }

mg_url_host

  • 简介:

    • 从给定的URL中提取主机名。
  • 原型:

    1
    struct mg_str mg_url_host(const char *url);
  • 参数:

    • url – 一个URL字符串
  • 返回值:

    • 主机名
  • 示例:

    1
    2
    struct mg_str a = mg_url_host("https://my.example.org:1234"); // a == "my.example.org"
    struct mg_str b = mg_url_host("tcp://[::1]"); // b == "[::1]"

mg_url_user

  • 简介:

    • 从给定的URL中提取用户名。
  • 原型:

    1
    struct mg_str mg_url_user(const char *url);
  • 参数:

    • url – 需要提取用户名的URL
  • 返回值:

    • 成功,返回用户名
    • 失败,返回空的字符串
  • 示例:

    1
    struct mg_str user_name = mg_url_user("https://user@password@my.example.org"); // user_name is now "user"

mg_url_pass

  • 简介:

    • 从给定的URL中提取密码
  • 原型:

    1
    struct mg_str mg_url_pass(const char *url);
  • 参数:

    • url – 需要提取密码的URL
  • 返回值:

    • 成功,返回密码
    • 失败,返回空的字符串
  • 示例:

    1
    struct mg_str pwd = mg_url_user("https://user@password@my.example.org"); // pwd is now "password"

mg_url_uri

  • 简介:

    • 从给定的URL中提取URI。注意,函数返回url内的指针;不需要明确地free()它。
  • 原型:

    1
    const char *mg_url_uri(const char *url);
  • 参数:

    • url – 需要提取URI的URL
  • 返回值:

    • 成功,返回URI字符串
    • 失败,返回 \
  • 示例:

    1
    const char *uri = mg_url_uri("https://example.org/subdir/subsubdir"); // `uri` is now pointer to "subdir/subsubdir"

简介

  • mongoose 工具

mg_call

  • 简介:

    • 发送ev事件到c事件处理程序。该函数在实现您自己的协议时非常有用。
  • 原型:

    1
    void mg_call(struct mg_connection *c, int ev, void *ev_data);
  • 参数:

    • c – 发送事件的连接
    • ev – 发送的事件
    • ev_data – 附加事件参数
  • 返回值:

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    // In a timer callback, send MG_EV_USER event to all connections
    static void timer_fn(void *arg) {
    struct mg_mgr *mgr = (struct mg_mgr *) arg;
    for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
    mg_call(c, MG_EV_USER, "hi!");
    }
    }

mg_error

  • 简介:

    • 向连接事件处理程序发送MG_EV_ERROR,并使用printf语义格式化错误信息。
  • 原型:

    1
    void mg_error(struct mg_connection *c, const char *fmt, ...);
  • 参数:

    • c – 发送事件的连接
    • fmt – 使用printf语义格式化的字符串
  • 返回值:

  • 示例:

    1
    mg_error(c, "Operation failed, error code: %d", errno);

简介

  • websocket相关函数

struct mg_ws_message

  • 简介:

    • 该结构代表Websocket消息。这个flag元素对应于RFC 6455第5.2节中所述的第一个字节。(https://www.rfc-editor.org/rfc/rfc6455#section-5.2)
  • 原型:

    1
    2
    3
    4
    struct mg_ws_message {
    struct mg_str data; // WebSocket message data
    uint8_t flags; // WebSocket message flags
    };

websocket message type

  • 简介:

    • 要从传入消息中提取消息类型,在结构体mg_ws_messageflag元素中检查四个LSBs
  • 可能存在的WebSocket消息类型:

    1
    2
    3
    4
    5
    6
    #define WEBSOCKET_OP_CONTINUE 0
    #define WEBSOCKET_OP_TEXT 1
    #define WEBSOCKET_OP_BINARY 2
    #define WEBSOCKET_OP_CLOSE 8
    #define WEBSOCKET_OP_PING 9
    #define WEBSOCKET_OP_PONG 10
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_WS_MSG) {
    struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
    msgtype = wm->flags & 0x0F;
    if (msgtype == WEBSOCKET_OP_BINARY) {
    // This is a binary data message
    } else if (msgtype == WEBSOCKET_OP_TEXT) {
    // This is a text data message
    }
    }
    }
  • 注:

    • 当调用mg_ws_send()ms_ws_printf()发送消息时,请使用RFC 6455第5.6节中所述的正确消息类型进行数据帧(https://www.rfc-editor.org/rfc/rfc6455#section-5.6)

mg_ws_connect

  • 简介:

    • 创建客户端Websocket连接。这个函数不能连接到对端,它仅仅分配需要的资源和启动连接进程。当对端真正连接好了,会向连接事件处理函数发送一个MG_EV_CONNECT事件
  • 原型:

    1
    struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fn_data, const char *fmt, ...);
  • 参数:

    • mgr – 使用的事件管理结构体
    • url – 指定的远程URL。例如:http://google.com
    • fn – 一个事件处理函数
    • fn_data – 一个任意指针,当事件处理函数被调用时,它会被作为fn_data传递。这个指针作为c->fn_data存储在连接结构体中
  • 返回值:

    • 返回一个指向创建的连接
    • 返回NULL表示错误
  • 示例

    1
    2
    3
    struct mg_connection *c = mg_ws_connect(&mgr, "ws://test_ws_server.com:1000",
    handler, NULL, "%s", "Sec-WebSocket-Protocol: echo\r\n");
    if(c == NULL) fatal("Cannot create connection");

mg_ws_upgrade

  • 简介:

    • 升级给定HTTP连接到Websocket。fmt是一个类似于printf()格式的字符串,用于额外的HTTP标头,返回给Websocket握手的客户端。如果不需要额外的标头,将fmt设置为空
  • 原型:

    1
    void mg_ws_upgrade(struct mg_connection *c, struct mg_http_message *, const char *fmt, ...);
  • 参数:

    • c – 使用的连接
    • hm – HTTP消息
    • fmt – 类似于printf的格式字符串,用于附加HTTP标头或为null
  • 返回值:

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    mg_ws_upgrade(c, hm, NULL); // Upgrade HTTP to WS
    }
    }

mg_ws_send

  • 简介:

    • 向WebSocket对端发送数据
  • 原型:

    1
    size_t mg_ws_send(struct mg_connection *c, const void *buf, size_t len, int op);
  • 参数:

    • c – 使用的连接
    • buf – 需要发送的数据
    • len – 需要发送的数据大小
    • op – WebSocket消息类型,参见WebSocket message type
  • 返回值:

    • 返回发送的字节数
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    // Mongoose events handler
    void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
    if (ev == MG_EV_WS_OPEN) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    mg_ws_send(c, "opened", 6, WEBSOCKET_OP_BINARY); // Send "opened" to web socket connection
    }
    }

mg_ws_printf, mg_ws_vprintf

  • 简介:

    • ms_ws_send()相同,但是使用printf()语义格式化数据
  • 原型:

    1
    2
    size_t mg_ws_printf(struct mg_connection *, int op, const char *fmt, ...);
    size_t mg_ws_vprintf(struct mg_connection *, int op, const char *fmt, va_list *);
  • 参数:

    • c – 使用的连接
    • op – WebSocket消息类型,参见WebSocket message type
    • fmt – 使用printf()语义格式化的字符串
  • 返回值:

    • 返回发送的字节数
  • 示例:

    1
    mg_ws_printf(c, WEBSOCKET_OP_TEXT, "Hello, %s!", "world");

mg_ws_wrap

  • 简介:

    • 将输出缓冲区中的数据转换为Websocket格式。有用然后通过WebSocket实施协议。具体示例参见examples/mqtt-over-ws-client
  • 原型:

    1
    size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op)
  • 参数:

    • c – 使用的连接
    • len – 转换的字节数
    • op – WebSocket消息类型
  • 返回值:

    • 返回连接结构体中输出缓冲区新的大小
  • 示例:

    1
    2
    3
    size_t len = c->send.len;         // Store output buffer len
    mg_mqtt_login(c, s_url, &opts); // Write MQTT login message
    mg_ws_wrap(c, c->send.len - len, WEBSOCKET_OP_BINARY); // Wrap it into WS

简介

  • 本教程将向你展示如何以一系列MJPEG帧的形式发送视频流。这里使用的技术是:
    • 以不可缓存的方式提供页面,并表明内容类型为multipart/x-mixed-replace。
    • 定期发送一个不同的JPEG文件的内容,取代以前的文件

单次文件上传大小为3MB

  • 修改宏MG_MAX_RECV_SIZE
    • mongoose.h中,宏MG_MAX_RECV_SIZE默认定义为3 * 1024 * 1024
    • 修改即可

文件上传问题

HTTP协议上传文件原理

HTTP 协议中的文件上传是通过 POST 请求来实现的,具体的原理如下:

  1. 客户端发送一个 HTTP POST 请求到服务器,并在请求头中指定 Content-Type 为 multipart/form-data。这告诉服务器该请求是一个包含多部分内容的表单数据。

  2. 服务器收到请求后,解析请求头中的 Content-Type,确认请求是一个文件上传请求。

  3. 客户端将要上传的文件分割成多个部分(或者称为数据包),每个数据包都包含一个文件的一部分内容。

  4. 客户端将每个数据包作为一个独立的部分,依次发送给服务器。每个数据包都会包含一些额外的元数据,例如文件名、文件类型等。

  5. 服务器接收到每个数据包后,根据数据包的元数据信息和内容进行处理。通常情况下,服务器会将接收到的数据包保存到临时文件或内存中。

  6. 当所有数据包都接收完毕后,服务器根据接收到的数据包重新构建原始文件,并将其保存到指定的位置。

需要注意的是,文件上传的过程中可能会涉及到数据包的分片、文件大小限制、上传进度监测等细节处理。一般来说,服务器端会提供相应的接口或库来处理文件上传,以简化开发过程。

Mongoose解决方案

  • 两种情况:
    • 要上传的文件很小–明显小于可用RAM的数量。例如,我们在一个有64MB内存的嵌入式Linux系统上运行Mongoose,并上传一些大小为1KB的JSON配置。在这种情况下,我们可以使用一个标准的HTML表单上传,并在一个POST请求中接收整个文件
    • 要上传的文件很大–与可用RAM的数量相比,或者明显超过这个数量。例如,我们想上传一个大小为512KB的新文件系统镜像到ESP8266设备上,该设备有大约30KB的可用RAM。在这种情况下,没有办法在内存中保存整个文件。它应该被分成小块处理,Mongoose应该接收每个小块并将其追加到写入的文件中,直到全部接收完毕。在这里,我们可以遵循两条路径:
      • 使用单个POST请求发送文件,将文件内容作为POST主体传递–即使用二进制上传。
      • 在客户端将文件分成小块(如2Kb),并将每个小块作为一个单独的POST请求发送。

form upload

binary upload, single POST

  • 当Mongoose收到一个大的HTTP请求时,它会缓冲传入的数据,对于每一个收到的数据块,它会产生MG_EV_HTTP_CHUNK请求。当一个完整的HTTP消息被缓冲时,那么最后一个零长度的MG_EV_HTTP_CHUNK被产生,然后是MG_EV_HTTP_MSG

  • 然而,服务器端可能不会等到完整的消息被缓冲在内存中,但它可以使用mg_http_delete_chunk()函数删除传入的chunk。如果块被删除,那么在最后一个零长度的块之后就不会产生MG_EV_HTTP_MSG。这样一来,服务器就可以在块到达时进行处理–例如,将块写入文件中。

  • MG_EV_HTTP_CHUNK消息也是为表单上传生成的。然而,Mongoose并不剥离多部分标记。如果表单上传的消息被保存到一个文件中,它将包含多部分标记。

  • 0长度的chunk是最后一个chunk。使用MG_IO_SIZE构建常数来限制服务器端的最大分块大小。

  • 服务器接收每个块,处理它并删除它。当收到最后一个分块时,发送一个响应。

简介

  • shell编程常用技巧

linux 目录下按照规则排序文件

在 Linux 中,可以使用 ls 命令结合不同的选项来按照规则排序目录下的文件。以下是一些常用的示例和方法:

1. 按文件名排序

默认情况下,ls 命令按文件名的字母顺序排序:

1
ls

2. 按文件大小排序

使用 -S 选项按文件大小排序:

1
ls -lS

3. 按修改时间排序

使用 -t 选项按修改时间排序:

1
ls -lt

4. 按访问时间排序

使用 -u 选项按访问时间排序:

1
ls -lu

5. 按文件创建时间排序(有些文件系统不支持)

使用 -c 选项按文件创建时间排序:

1
ls -lc

6. 逆序排序

使用 -r 选项逆序排列:

1
ls -lr

7. 按扩展名排序

使用 --sort=extension 按扩展名排序:

1
ls -l --sort=extension

8. 按文件大小排序并显示人类可读格式

使用 -h 选项结合 -S 选项:

1
ls -lSh

9. 按指定规则排序文件

结合 findsort 命令,可以按照更加复杂的规则进行排序。例如,按文件大小排序:

1
find . -type f -exec ls -l {} + | sort -k 5 -n

10. 按文件名排序,并忽略大小写

使用 -f 选项结合 sort 命令:

1
ls | sort -f

示例

假设有一个目录,里面包含以下文件:

1
2
3
4
5
file1.txt
file2.txt
fileA.txt
fileB.txt
file10.txt

按文件名排序(忽略大小写)

1
ls | sort -f

输出:

1
2
3
4
5
file1.txt
file10.txt
file2.txt
fileA.txt
fileB.txt

按文件大小排序

1
ls -lS

输出(假设文件大小分别为 100B, 200B, 150B, 50B, 250B):

1
2
3
4
5
-rw-r--r-- 1 user group  250 Apr 10 10:00 file10.txt
-rw-r--r-- 1 user group 200 Apr 10 10:00 file2.txt
-rw-r--r-- 1 user group 150 Apr 10 10:00 fileA.txt
-rw-r--r-- 1 user group 100 Apr 10 10:00 file1.txt
-rw-r--r-- 1 user group 50 Apr 10 10:00 fileB.txt

总结

通过结合使用 ls 命令的不同选项以及 sort 命令,你可以根据各种规则对目录下的文件进行排序。选择适合你需求的命令和选项,并根据需要进行调整。

shell 字符串分割

在 Shell 中,可以使用多种方法来分割字符串。下面是几种常见的方法:

1. 使用 IFS(内部字段分隔符)

使用 IFS 变量可以轻松地将字符串分割成数组。以下是一个示例,将逗号分隔的字符串分割成数组:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash

str="apple,banana,cherry"
IFS=',' read -r -a array <<< "$str"

# 输出数组元素
for element in "${array[@]}"
do
echo "$element"
done

2. 使用 cut

cut 命令可以从字符串中提取字段。以下是一个示例,使用逗号作为分隔符:

1
2
3
4
5
6
#!/bin/bash

str="apple,banana,cherry"
echo "$str" | cut -d',' -f1 # apple
echo "$str" | cut -d',' -f2 # banana
echo "$str" | cut -d',' -f3 # cherry

3. 使用 awk

awk 是一个强大的文本处理工具,可以用来分割字符串。以下是一个示例:

1
2
3
4
5
6
#!/bin/bash

str="apple,banana,cherry"
echo "$str" | awk -F',' '{print $1}' # apple
echo "$str" | awk -F',' '{print $2}' # banana
echo "$str" | awk -F',' '{print $3}' # cherry

4. 使用 trwhile 循环

tr 命令可以用来替换字符。结合 while 循环,可以逐个处理字符串中的每个部分。以下是一个示例:

1
2
3
4
5
6
7
#!/bin/bash

str="apple,banana,cherry"
echo "$str" | tr ',' '\n' | while read element
do
echo "$element"
done

5. 使用参数扩展

在 Bash 中,还可以使用参数扩展进行简单的字符串分割:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

str="apple,banana,cherry"

# 截取第一个逗号前的部分
part1="${str%%,*}"
echo "$part1" # apple

# 截取第一个逗号后的部分
remaining="${str#*,}"

# 再次截取
part2="${remaining%%,*}"
echo "$part2" # banana
part3="${remaining#*,}"
echo "$part3" # cherry

这些方法可以帮助你在 Shell 脚本中进行字符串分割。选择最适合你需求的方法,并根据需要调整分隔符和字符串。

在shell script中以某用户身份执行命令

1
2
3
#!/bin/bash 
sudo -S bash -c 'whoami'
whoami

linux 写一个定时刷新的24h运行脚本

你可以使用crontab来创建一个定时刷新的脚本。crontab是一个用于在Linux系统上定期执行任务的工具。下面是一个示例,假设你有一个名为refresh.sh的脚本,你想每天定时运行:

首先,创建一个refresh.sh脚本:

1
2
3
4
5
6
7
8
#!/bin/bash

# 这是你的刷新任务脚本内容
# 例如,你可以在这里写下你想要执行的任务
# 比如,刷新某个文件夹下的内容

echo "Running refresh script at $(date)"
# 在这里执行你的刷新任务

保存并退出。

接下来,编辑你的crontab

1
crontab -e

在编辑器中添加以下行,表示每天的0点执行refresh.sh脚本:

1
0 0 * * * /path/to/refresh.sh

确保将/path/to/refresh.sh替换为你实际的refresh.sh脚本的路径。

保存并退出编辑器。

这将使你的refresh.sh脚本每天的午夜被执行,从而实现了24小时定时刷新的需求。

linux stat 获取指定目录的空闲空间

你可以使用 stat 命令获取文件系统的信息,但是 stat 命令不能直接获取指定目录的空闲空间。要获取指定目录的空闲空间,你可以使用 df 命令。

以下是一个示例 Bash 脚本,用于获取指定目录的空闲空间:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

# 指定要获取空间信息的目录
directory="/path/to/your/directory"

# 获取目录所在的文件系统
filesystem=$(df -P "$directory" | awk 'NR==2 {print $1}')

# 获取文件系统的空闲空间
free_space=$(df -P "$filesystem" | awk 'NR==2 {print $4}')

echo "Free space in $directory : $free_space"

在这个脚本中,你需要将 /path/to/your/directory 替换为你要查询空间信息的目录路径。脚本将首先使用 df 命令获取该目录所在的文件系统,然后再次使用 df 命令获取该文件系统的空闲空间。最后,脚本会输出空闲空间的信息。

请注意,这个脚本只是一个简单的示例,适用于大多数情况。在实际使用中,你可能需要更复杂的逻辑来确保脚本的稳健性和安全性。

linux bash 字符串删除

如果你要删除字符串中的特定字符或子字符串,你可以使用 Bash 的内置功能 sedawk 或字符串操作函数来实现。下面是一些方法示例:

使用 sed 删除字符串中的字符:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash

# 原始字符串
original_string="Hello World"

# 删除字符串中的空格
modified_string=$(echo "$original_string" | sed 's/ //g')

echo "Original string: $original_string"
echo "Modified string: $modified_string"

使用 awk 删除字符串中的字符:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash

# 原始字符串
original_string="Hello World"

# 删除字符串中的空格
modified_string=$(echo "$original_string" | awk '{gsub(" ", "")}1')

echo "Original string: $original_string"
echo "Modified string: $modified_string"

使用字符串操作函数删除字符串中的子字符串:

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash

# 原始字符串
original_string="Hello World"

# 删除字符串中的 "llo" 子字符串
substring_to_remove="llo"
modified_string="${original_string//$substring_to_remove}"

echo "Original string: $original_string"
echo "Modified string: $modified_string"

这些示例中,原始字符串是 “Hello World”,然后使用不同的方法删除了其中的空格或子字符串。你可以根据自己的需求选择其中一种方法。

linux bash 获取docker容器的id

要获取正在运行的 Docker 容器的 ID,你可以使用 Docker 命令行工具。以下是使用 docker ps 命令来获取正在运行容器的 ID 的示例:

1
2
3
4
5
6
#!/bin/bash

# 获取正在运行的容器的 ID
container_id=$(docker ps -q)

echo "Running Docker container ID: $container_id"

在这个脚本中,docker ps -q 命令用于列出正在运行的容器,并使用 -q 参数只显示容器的 ID。然后将结果存储在 container_id 变量中,并输出该变量的值。

这只会获取第一个正在运行的容器的 ID。如果你想获取特定容器的 ID,你可以使用 docker ps -qf 命令并提供过滤条件,如容器的名称、标签等。例如,要获取名称为 my_container 的容器的 ID,你可以使用以下命令:

1
container_id=$(docker ps -qf "name=my_container")

你可以根据自己的需要调整这些命令。

linux find命令找到指定文件并保存到数组中

在Linux中,find命令用于查找文件和目录。如果你想使用find命令找到指定文件并将结果保存到一个数组中,你可以使用以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1. 使用 find 命令查找指定文件,并将结果保存到数组
files_array=($(find /path/to/search -name "your_pattern"))

# 2. 输出数组内容(可选)
echo "Files found:"
for file in "${files_array[@]}"; do
echo "$file"
done

cmd="libtool -static -o libabsl.a "

for file in "${files_array[@]}"; do
cmd="${cmd} ${file}"
done

echo "cmd:"
echo ${cmd}

在这个例子中:

  • /path/to/search 是你要搜索的目录的路径。
  • "your_pattern" 是你要匹配的文件名模式。你可以使用通配符来匹配文件名的一部分,比如 *.txt 表示所有以 .txt 结尾的文件。
  • files_array 是保存文件列表的数组。

请注意,上述代码假设文件和目录名不包含空格。如果你的文件名中可能包含空格,建议使用更复杂的方法来处理,比如使用 find 命令的 -print0 选项以及 readarray 命令:

1
2
3
4
5
6
7
8
# 使用 find 命令查找指定文件,将结果以空字符分隔保存到数组
readarray -d '' files_array < <(find /path/to/search -name "your_pattern" -print0)

# 输出数组内容
echo "Files found:"
for file in "${files_array[@]}"; do
echo "$file"
done

这种方法通过 -print0 选项和 readarray -d '' 的配合,确保了对文件名中可能包含的空格进行正确处理。

简介

  • shell脚本编程的常用方法

linux shell 创建数组并在for循环中向数组添加元素

在 Bash 中,你可以在 for 循环中向数组添加元素。以下是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

# 创建一个空数组
my_array=()

# 在 for 循环中向数组添加元素
for i in {1..5}
do
my_array+=("$i")
done

# 打印数组中的所有元素
for item in "${my_array[@]}"
do
echo "$item"
done

在这个示例中,我们首先创建了一个空数组 my_array。然后,在 for 循环中,我们使用 += 运算符向数组添加了 1 到 5 的数字。最后,我们使用另一个 for 循环遍历数组并打印出所有的元素。

这样做会将每个数字作为一个独立的数组元素添加到数组中。

linux shell 创建数组

在 Bash 中创建数组很简单,只需在变量名前加上 () 并用空格分隔元素即可。以下是一个示例:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash

# 创建一个数组
my_array=("apple" "banana" "orange" "grape")

# 打印数组中的所有元素
for fruit in "${my_array[@]}"
do
echo "$fruit"
done

这个脚本创建了一个名为 my_array 的数组,其中包含了几种水果。然后,通过 for 循环遍历数组中的每个元素,并将其打印出来。

你也可以在创建数组后,通过索引访问和修改数组中的元素。例如:

1
2
3
4
5
# 访问数组元素
echo "${my_array[0]}" # 输出第一个元素 "apple"

# 修改数组元素
my_array[1]="pear" # 将第二个元素修改为 "pear"

这些都是 Bash 中创建和操作数组的基本方法。

linux shell脚本 获取指定目录下的所有文件名并依次判断是文件还是目录

你可以通过 for 循环遍历指定目录下的所有文件和目录,并使用 test 命令检查每个项目是文件还是目录。以下是一个示例脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash

# 指定目录路径
directory="/path/to/directory"

# 获取目录下所有文件和目录名,并遍历
for item in "$directory"/*
do
# 判断是否为文件
if [ -f "$item" ]; then
echo "$item 是一个文件"
# 判断是否为目录
elif [ -d "$item" ]; then
echo "$item 是一个目录"
else
echo "$item 不是文件也不是目录"
fi
done

这个脚本会遍历指定目录下的所有文件和目录,并输出相应的信息。你可以根据需要修改 directory 变量来指定不同的目录路径。

linux shell脚本 获取指定目录下的所有文件名并保存到数组

你可以编写一个 shell 脚本来获取指定目录下的所有文件名,并将它们保存到一个数组中。以下是一个示例脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash

# 指定目录路径
directory="/path/to/directory"

# 获取目录下所有文件名,并保存到数组
file_list=($(ls "$directory"))

# 打印数组中的所有文件名
for file in "${file_list[@]}"
do
echo "$file"
done

将上述脚本保存为一个文件,比如 list_files.sh,然后赋予执行权限:

1
chmod +x list_files.sh

最后,运行该脚本即可:

1
./list_files.sh

这个脚本会将指定目录下的所有文件名保存到 file_list 数组中,并打印出来。你可以根据需要修改 directory 变量来指定不同的目录路径。

linux shell 字符串拼接

在Linux Shell中,你可以使用不同的方法来进行字符串拼接,具体取决于你使用的Shell(例如,Bash、Zsh、Fish等)。以下是一些常见的方法:

  1. 使用+操作符(仅限Bash和Zsh):

    1
    2
    3
    4
    str1="Hello, "
    str2="world!"
    result="$str1$str2"
    echo "$result"

    这将会输出:Hello, world!

  2. 使用${}来拼接字符串(适用于大多数Shell):

    1
    2
    3
    4
    str1="Hello, "
    str2="world!"
    result="${str1}${str2}"
    echo "$result"

    输出与上述相同。

  3. 使用printf函数来拼接字符串(适用于大多数Shell):

    1
    2
    3
    4
    str1="Hello, "
    str2="world!"
    result=$(printf "%s%s" "$str1" "$str2")
    echo "$result"

    输出与上述相同。

  4. 使用命令替换来拼接字符串(适用于大多数Shell):

    1
    2
    3
    4
    str1="Hello, "
    str2="world!"
    result=$(echo "${str1}${str2}")
    echo "$result"

    输出与上述相同。

  5. 在echo中直接拼接字符串:

    1
    2
    3
    str1="Hello, "
    str2="world!"
    echo "${str1}${str2}"

    这将直接输出拼接后的字符串。

  6. 使用Here Document(适用于大多数Shell):

    1
    2
    3
    4
    5
    6
    7
    str1="Hello, "
    str2="world!"
    result=$(cat <<EOF
    ${str1}${str2}
    EOF
    )
    echo "$result"

    这种方法适用于多行字符串拼接。

请注意,上述示例中的字符串拼接方法可以在大多数常见的Shell中使用,但可能会有一些细微的差异。确保根据你所使用的Shell来选择适当的方法。

linux bash shell 字符串拼接

在Bash Shell中,你可以使用不同的方法来进行字符串拼接。以下是一些常见的方法:

  1. 使用${}来拼接字符串:
1
2
3
4
str1="Hello, "
str2="world!"
result="${str1}${str2}"
echo "$result"

这将会输出:Hello, world!

  1. 使用+操作符(仅限Bash 4.0及更高版本):
1
2
3
4
str1="Hello, "
str2="world!"
result="$str1$str2"
echo "$result"

这也会输出:Hello, world!

  1. 使用+=操作符来追加字符串:
1
2
3
str1="Hello, "
str1+="world!"
echo "$str1"

这将输出:Hello, world!

  1. 使用命令替换来拼接字符串:
1
2
3
4
str1="Hello, "
str2="world!"
result=$(echo "${str1}${str2}")
echo "$result"

这也会输出:Hello, world!

  1. 在echo中直接拼接字符串:
1
2
3
str1="Hello, "
str2="world!"
echo "${str1}${str2}"

这将直接输出拼接后的字符串。

请根据你的需求和个人偏好选择合适的字符串拼接方法。在Bash中,上述示例中的任何一种方法都可以使用。

将命令输出的信息存储到数组

在Linux Shell中,可以使用命令替换和数组来将命令的输出存储到一个数组中。有两种常用的方式来实现这个目标,分别是使用$()或反引号``来进行命令替换。

假设你要将ls命令的输出存储到一个数组中,可以按照以下方式进行操作:

使用$()进行命令替换:

1
2
3
4
5
6
7
# 将ls命令的输出存储到数组files中
files=($(ls))

# 输出数组元素
for file in "${files[@]}"; do
echo "$file"
done

使用反引号``进行命令替换:

1
2
3
4
5
6
7
# 将ls命令的输出存储到数组files中
files=`ls`

# 输出数组元素
for file in "${files[@]}"; do
echo "$file"
done

需要注意的是,如果文件名中包含空格或特殊字符,使用上述方法存储到数组中可能会导致文件名分割错误。为了避免这种情况,建议使用read命令来逐行读取命令输出,然后将每行存储到数组中:

1
2
3
4
5
6
7
# 使用read命令逐行读取ls命令的输出并存储到数组files中
IFS=$'\n' read -d '' -r -a files < <(ls)

# 输出数组元素
for file in "${files[@]}"; do
echo "$file"
done

这种方法可以正确处理文件名中包含空格或特殊字符的情况。

请注意,存储命令输出到数组时,输出中的每个元素会根据换行符进行分割。如果输出是以空格或其他分隔符分隔的,可以使用IFS变量来设置分隔符。例如,如果输出是以空格分隔的,可以设置IFS=' '

判断变量是否为空

在 Linux Shell 脚本中,可以使用不同的方式来判断一个变量是否为空。以下是几种常用的方法:

  1. 使用 if-else 语句

    1
    2
    3
    4
    5
    if [ -z "$var" ]; then
    echo "变量为空"
    else
    echo "变量不为空"
    fi

    在上述示例中,使用 -z 表达式来判断变量 $var 是否为空。如果为空,则执行 if 语句块中的命令;如果不为空,则执行 else 语句块中的命令。

  2. 使用双引号和等号比较

    1
    2
    3
    4
    5
    if [ "$var" = "" ]; then
    echo "变量为空"
    else
    echo "变量不为空"
    fi

    这种方式使用双引号将变量引起来,并与空字符串进行等号比较,判断变量是否为空。

  3. 使用双括号和双引号

    1
    2
    3
    4
    5
    if [[ -z "$var" ]]; then
    echo "变量为空"
    else
    echo "变量不为空"
    fi

    在这种方式中,使用双括号 [[ ... ]] 来进行条件判断,并使用双引号将变量引起来。

需要注意的是,变量前面的 $ 符号需要加上双引号,这样可以避免在变量为空时引发语法错误。

这些是常用的方式来判断一个变量是否为空。根据具体的需求和脚本环境,您可以选择适合您的方式来进行变量的判空操作。

希望这些解释对您有所帮助!如果您有更多问题,请随时提问。

获取时间

在 Shell 脚本中,可以使用 date 命令来获取当前的时间和日期。

要获取当前的完整时间,可以使用以下命令:

1
2
current_time=$(date +%T)
echo "当前时间:$current_time"

该命令使用 %T 格式化选项来获取当前时间,并将结果保存在 current_time 变量中。

如果你只需要获取当前的日期,可以使用以下命令:

1
2
current_date=$(date +%F)
echo "当前日期:$current_date"

这里使用 %F 格式化选项来获取当前日期,并将结果保存在 current_date 变量中。

date 命令还有很多其他的格式化选项,你可以根据需求选择适合你的日期和时间格式。使用 man date 命令可以查看 date 命令的完整文档,其中包含了所有的格式化选项和用法示例。

除了 date 命令,还可以使用其他 Shell 内建的变量来获取当前时间和日期。例如:

  • 获取当前时间戳:

    1
    2
    current_timestamp=$(date +%s)
    echo "当前时间戳:$current_timestamp"
  • 获取当前年份:

    1
    2
    current_year=$(date +%Y)
    echo "当前年份:$current_year"
  • 获取当前月份:

    1
    2
    current_month=$(date +%m)
    echo "当前月份:$current_month"

等等,根据具体需求选择适合的日期和时间信息。


gsettings 常用示例

以下是一些常见的 gsettings 命令示例,涵盖了不同的设置类别:

  1. 修改桌面背景图片:

    1
    gsettings set org.gnome.desktop.background picture-uri 'file:///path/to/image.jpg'
  2. 修改桌面壁纸平铺方式:

    1
    gsettings set org.gnome.desktop.background picture-options 'scaled'
  3. 修改桌面图标显示/隐藏:

    1
    gsettings set org.gnome.desktop.background show-desktop-icons false
  4. 修改窗口主题:

    1
    gsettings set org.gnome.desktop.wm.preferences theme 'Adwaita'
  5. 修改默认浏览器:

    1
    gsettings set org.gnome.desktop.default-applications.web-browser 'firefox.desktop'
  6. 修改鼠标双击行为:

    1
    gsettings set org.gnome.desktop.peripherals.mouse double-click true
  7. 修改键盘重复延迟和速度:

    1
    2
    gsettings set org.gnome.desktop.peripherals.keyboard delay 200
    gsettings set org.gnome.desktop.peripherals.keyboard repeat-interval 20
  8. 修改屏幕亮度调节方式:

    1
    gsettings set org.gnome.settings-daemon.plugins.power idle-dim false

这些示例只是 gsettings 命令的一小部分。你可以通过查阅相关的文档或使用 gsettings list-schemasgsettings list-keys SCHEMA 等命令来探索更多可用的设置和键。

请注意,命令中的 SCHEMAKEY 根据要修改的设置不同而有所变化。确保替换命令中的占位符为适当的值。


gsettings 打开 关闭 代理

在Ubuntu中,你可以使用gsettings命令来打开和关闭代理设置。以下是相关的命令示例:

打开代理:

1
2
3
gsettings set org.gnome.system.proxy mode 'manual'
gsettings set org.gnome.system.proxy.http host 'proxy.example.com'
gsettings set org.gnome.system.proxy.http port 8080

'proxy.example.com' 替换为你的代理服务器地址,8080 替换为代理服务器端口号。

关闭代理:

1
gsettings set org.gnome.system.proxy mode 'none'

这些命令将设置系统代理模式为手动(manual)并指定代理服务器的地址和端口。关闭代理时,将把系统代理模式设置为无(none)。

请注意,这些命令基于 GNOME 桌面环境的代理设置。如果你使用的是其他桌面环境,可能会有不同的命令或配置文件用于管理代理设置。

另外,使用gsettings命令修改的代理设置将在整个系统范围内生效,包括各个应用程序和网络连接。你可能需要重新启动一些应用程序或系统才能使代理设置生效。


linux Ctrl 快捷命令

在Linux中,Ctrl键(Control键)结合其他键组合可以触发各种快捷命令。下面是一些常用的Ctrl快捷键及其功能的详细解释:

  1. Ctrl+C:发送中断信号(SIGINT)给当前正在前台运行的进程,用于中断(终止)进程的执行。

  2. Ctrl+Z:发送暂停信号(SIGTSTP)给当前正在前台运行的进程,将其挂起并放入后台。可以使用fg命令将其重新放到前台运行,或使用bg命令将其转换为后台运行。

  3. Ctrl+D:表示输入流结束,用于退出交互式shell。当你在终端中输入Ctrl+D时,它会告诉shell当前输入结束,然后触发相应的行为,如关闭当前终端会话或退出交互式程序。

  4. Ctrl+L:清除终端屏幕,等效于使用clear命令。它将当前终端窗口的内容滚动到顶部,使终端屏幕变为空白。

  5. Ctrl+A:将光标移到命令行的开头。

  6. Ctrl+E:将光标移到命令行的末尾。

  7. Ctrl+K:删除光标位置到命令行末尾的文本。

  8. Ctrl+U:删除光标位置到命令行开头的文本。

  9. Ctrl+W:删除光标之前的一个单词。

  10. Ctrl+R:在命令历史中进行反向搜索。

  11. Ctrl+G:取消当前的编辑或操作,放弃正在进行的命令。

这些是一些常见的Ctrl快捷键,在Linux终端中使用频率很高。它们可以帮助你更高效地控制终端会话、编辑命令行以及与进程进行交互。请注意,某些快捷键在特定的应用程序或环境中可能会有不同的功能或效果。


linux alt 快捷命令

在Linux中,Alt键(也称为Meta键或Option键)结合其他键组合可以触发各种快捷命令。下面是一些常用的Alt快捷键及其功能的简要说明:

  1. Alt+Tab:在打开的窗口之间切换。按下Alt键并保持按住,然后连续按下Tab键可以切换到下一个窗口。松开Alt键时,所选的窗口将被激活。

  2. Alt+F4:关闭当前活动的窗口。按下Alt键并保持按住,然后按下F4键可以关闭当前窗口。

  3. Alt+Space:打开窗口菜单。按下Alt键并保持按住,然后按下Space键可以打开当前窗口的菜单选项,例如最大化、最小化、移动等。

  4. Alt+Enter:在终端中切换全屏模式。按下Alt键并保持按住,然后按下Enter键可以在终端窗口之间切换全屏模式。

  5. Alt+Up/Down:在终端中上下滚动。按下Alt键并保持按住,然后按下上箭头或下箭头键可以在终端中上下滚动输出。

  6. Alt+Left/Right:在终端中左右切换。按下Alt键并保持按住,然后按下左箭头或右箭头键可以在终端中左右切换命令。

这些是一些常见的Alt快捷键,在Linux中使用频率较高。请注意,某些快捷键可能因特定的桌面环境、窗口管理器或应用程序而有所不同。此外,Alt键也常用于与其他键组合以实现特定功能,具体取决于应用程序的键绑定设置。

clear 清除屏幕信息 ctrl+L

在Linux中,clear命令用于清除当前终端窗口上的内容,使其变为空白屏幕,以提供一个干净的工作环境。

使用clear命令非常简单,只需在终端中键入以下命令即可:

1
clear

执行该命令后,当前终端窗口中的所有文本和输出将被清除,终端将变为空白屏幕,光标回到终端的起始位置。

clear命令常用于清除终端中的大量输出或命令的执行结果,以便获得更好的可读性和清晰度。当终端窗口中显示的内容过多或杂乱时,使用clear命令可以快速清除屏幕并重新开始。

需要注意的是,clear命令只会清除当前终端窗口的内容,并不会影响其他终端或窗口的显示。当你切换到其他终端或打开新的终端窗口时,之前的内容仍然可见。

除了clear命令,你也可以使用快捷键Ctrl + L来达到相同的效果,它可以清除当前终端窗口的内容。

总结起来,clear命令用于清除当前终端窗口的内容,使其变为空白屏幕。这是一个简单但实用的命令,可以提供一个干净的工作环境。


查看目录下所有文件的行数

要查看Linux中一个目录下所有文件的行数,可以使用find命令与wc命令的组合。以下是一个示例命令:

1
find /path/to/directory -type f -exec cat {} + | wc -l

请替换/path/to/directory为你想要查看的目录的实际路径。

该命令的解释如下:

  • find /path/to/directory:查找指定目录下的所有文件。
  • -type f:限定只查找普通文件,排除目录和其他特殊文件。
  • -exec cat {} +:对找到的每个文件执行cat命令,将文件内容输出到标准输出。
  • |:将cat命令的输出通过管道传递给下一个命令。
  • wc -l:对输入进行行数统计,输出总行数。

执行该命令后,会输出指定目录下所有文件的总行数。

请注意,如果目录下的文件较多或文件较大,这个命令可能需要一些时间来完成执行。另外,该命令只统计文件中的行数,不包括空行和文件夹的行数。


根据进程名 获取进程id

在Shell脚本中,可以使用pgrep命令来根据进程名获取进程ID(PID)。pgrep命令可以根据进程名模式匹配正在运行的进程,并返回符合条件的进程ID。

以下是一个示例Shell脚本,演示如何使用pgrep命令获取进程ID:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

process_name="example_process" # 设置进程名

# 使用pgrep命令获取进程ID
pid=$(pgrep "$process_name")

if [ -n "$pid" ]; then
echo "进程 $process_name 的PID为: $pid"
else
echo "未找到进程 $process_name"
fi

在上述示例中,首先定义了要查找的进程名为example_process。然后,使用pgrep命令和进程名作为参数来获取进程ID。如果找到了符合条件的进程,$pid变量将保存进程ID,并打印出来。如果未找到进程,则打印相应的提示信息。

可以将上述脚本保存为.sh文件,并在Shell环境中运行,即可根据进程名获取进程ID。

需要注意的是,pgrep命令还支持其他选项,如根据用户、进程所属终端等条件进行进程查找。您可以通过man pgrep命令查看pgrep命令的详细用法和选项。