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

文章详细介绍了mongoose库中mg_mgr_init函数的执行过程,包括初始化操作、user_data处理,以及mg_ifaces和mg_default_iface_vtable的结构和作用,特别提到了socket接口函数指针的设置和SSL支持。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        在用 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,这个就是函数指针接口的集合了:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值