mongoose源码解读(二) -- mg_mgr_init 初始化

        在用 mongoose 源码开发的时候,这个初始化函数 mg_mgr_init()则是必须的,我们看下它到底做了哪些初始化操作。

void mg_mgr_init(struct mg_mgr *m, void *user_data) {struct mg_mgr_init_opts opts;memset(&opts, 0, sizeof(opts));mg_mgr_init_opt(m, user_data, opts);
}

我们是这样调用的 mg_mgr_init(&mgr, nullptr); 所以 user_data 指针为 nullptr, 所以mg_mgr_init_opt() 里后两个参数是都是空的。

用户数据指针赋给了入参 m->user_data,接下来就是 interface 相关的赋值了,因为 m->ifaces 是二级指针,所以给它申请了内存:

 

 这里用到了一个全局变量 mg_ifaces,它的定义是这样的

const struct mg_iface_vtable *mg_ifaces[] = {&mg_default_iface_vtable,
};

而这个 mg_default_iface_vtable 就是函数指针的集合,

#define MG_SOCKET_IFACE_VTABLE                                          \{                                                                     \mg_socket_if_init,                                                  \mg_socket_if_free,                                                  \mg_socket_if_add_conn,                                              \mg_socket_if_remove_conn,                                           \mg_socket_if_poll,                                                  \mg_socket_if_listen_tcp,                                            \mg_socket_if_listen_udp,                                            \mg_socket_if_connect_tcp,                                           \mg_socket_if_connect_udp,                                           \mg_socket_if_tcp_send,                                              \mg_socket_if_udp_send,                                              \mg_socket_if_tcp_recv,                                              \mg_socket_if_udp_recv,                                              \mg_socket_if_create_conn,                                           \mg_socket_if_destroy_conn,                                          \mg_socket_if_sock_set,                                              \mg_socket_if_get_conn_addr,                                         \}#if MG_NET_IF == MG_NET_IF_SOCKET
const struct mg_iface_vtable mg_default_iface_vtable = MG_SOCKET_IFACE_VTABLE;
#endif

这些函数指针集合就是对应这个包含了函数指针定义的结构体:

struct mg_iface_vtable {void (*init)(struct mg_iface *iface);void (*free)(struct mg_iface *iface);void (*add_conn)(struct mg_connection *nc);void (*remove_conn)(struct mg_connection *nc);time_t (*poll)(struct mg_iface *iface, int timeout_ms);/* Set up a listening TCP socket on a given address. rv = 0 -> ok. */int (*listen_tcp)(struct mg_connection *nc, union socket_address *sa);/* Request that a "listening" UDP socket be created. */int (*listen_udp)(struct mg_connection *nc, union socket_address *sa);/* Request that a TCP connection is made to the specified address. */void (*connect_tcp)(struct mg_connection *nc, const union socket_address *sa);/* Open a UDP socket. Doesn't actually connect anything. */void (*connect_udp)(struct mg_connection *nc);/* Send functions for TCP and UDP. Sent data is copied before return. */int (*tcp_send)(struct mg_connection *nc, const void *buf, size_t len);int (*udp_send)(struct mg_connection *nc, const void *buf, size_t len);int (*tcp_recv)(struct mg_connection *nc, void *buf, size_t len);int (*udp_recv)(struct mg_connection *nc, void *buf, size_t len,union socket_address *sa, size_t *sa_len);/* Perform interface-related connection initialization. Return 1 on ok. */int (*create_conn)(struct mg_connection *nc);/* Perform interface-related cleanup on connection before destruction. */void (*destroy_conn)(struct mg_connection *nc);/* Associate a socket to a connection. */void (*sock_set)(struct mg_connection *nc, sock_t sock);/* Put connection's address into *sa, local (remote = 0) or remote. */void (*get_conn_addr)(struct mg_connection *nc, int remote,union socket_address *sa);
};

所以像源码里发送、接收数据的调用都是这样调用的:

nc->iface->vtable->tcp_send

nc->iface->vtable->tcp_recv

那调用的都是上面的函数指针,如果是启用了 ssl 的可能又是另外一套函数指针接口了。

其实我们还可以从 GDB 里看到:

active_connections 保存的就是 struct mg_connection *con = mg_bind(&mgr, buf, nullptr); 这个con:

 

 然后看mgr 里的 ifaces 是二级指针,看一下它的值:

二级指针,解引用两次得到它里面的内容,而这个 vtable 又是一个指针,它指向了 mg_default_iface_vtable,这个就是函数指针接口的集合了:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/498657.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣-移除元素

问题 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长…

深入Linux内核(进程篇)—进程切换之ARM体系架构 简单总结

context_switch函数完成Arm架构Linux进程切换,调用两个函数: 调用switch_mm() 完成用户空间切换,刷新I-CACHE,处理ASID和TLB,页表转换基址切换(即把TTBR0寄存器的值设置为新进程的PGD)&#xf…

java自动化之自动化框架项目(第四天-常用变量解析到map)

1.实现目标 常用变量解析到map,方便后面解析初始化sql或者入参的时候对变量进行替换 2.添加工具类 VariableUtil.java package com.syq.autotest.utils;import com.syq.autotest.entity.Variable; import org.apache.log4j.Logger;import java.util.HashMap; imp…

AI大模型 拍照搜题

最近,发现一款小程序【问智通】,实现了拍照搜题结合AI大模型,省去了打字和敲数学公式向AI提问,完美的补充了其它拍照搜题平台拍不到,没解析等不足!!! 小程序码: APP下载…

map和set的简单介绍

由于博主的能力有限,所以为了方便大家对于map和set的学习,我放一个官方的map和set的链接供大家参考: https://cplusplus.com/ 在初阶阶段,我们已经接触过STL中的部分容器,比如:vector、list、deque&#x…

四、《任务列表案例》后端程序实现和测试

本章概要 准备工作功能实现前后联调 4.1 准备工作 数据库脚本 CREATE TABLE schedule (id INT NOT NULL AUTO_INCREMENT,title VARCHAR(255) NOT NULL,completed BOOLEAN NOT NULL,PRIMARY KEY (id) );INSERT INTO schedule (title, completed) VALUES(学习java, true),(学…

Tkinter.Text控件中,文本存在某个关键字的将被高亮显示(标记颜色+字体加粗)

在Tkinter的Text控件中,要标记某个关键字并改变其颜色,你可以使用tag_add方法来给包含关键字的文本添加标签,然后使用tag_config方法来配置该标签的显示样式,包括前景色(字体颜色)和背景色等。以下是一个完…

《2024年网络钓鱼现状全球报告》解读

文章目录 前言一、报告解读二、最常见的与员工相关的网络安全漏洞三、员工的网络安全“责任认知”四、真实的安全意识培训与钓鱼演练覆盖率不足前言 Proofpoint年度报告简述基于对15个国家的7500名终端用户和1050名网络安全专业人士的调研。难能可贵的是,本报告不仅基于主观调…

leetcode — 动态规划 — 打家劫舍、完全平方数

1 打家劫舍 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房…

Windows系统安装TortoiseSVN并结合内网穿透实现远程访问本地服务器——“cpolar内网穿透”

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统,它与Apache Subversion(SVN)集成在一起,提供了一个用户友好的界面,方便用…

4_相机透镜畸变

理论上讲,是可能定义一种透镜而不引入任何畸变的。然而现实世界没有完美的透镜。这主要是制造上的原因,因为制作一个“球形”透镜比制作一个数学上理想的透镜更容易。而且从机械方面也很难把透镜和成像仪保持平行。下面主要描述两种主要的透镜畸变并为他…

Java最全面试总结——7.MySQL篇

1、数据库的三范式是什么? 第一范式(1st Normal Form, 1NF): 定义:确保数据库中的每个属性都是原子的,即不可再分的。应用:每个属性的值不能包含多个值或重复的值。目的:消除数据中的…