【Libevent--链接侦听器evconnlistener_new_bind 代码、参数解析附sockaddr_in解析】一键完成套接字的创建、监听、绑定、提取-回调

evconnlistener_new_bind 是 Libevent 库中的一个函数,用于分配一个监听器对象,并监听给定地址上的 TCP 连接。下面是关于 evconnlistener_new_bind 函数的详细解析:

函数原型

struct evconnlistener* evconnlistener_new_bind(  
    struct event_base* base,  
    evconnlistener_cb cb,  
    void* ptr,  
    unsigned flags,  
    int backlog,  
    const struct sockaddr* sa,  
    int socklen  
);

参数说明

base:

类型:struct event_base*
描述:关联的 Libevent 框架上下文。

cb:

类型:evconnlistener_cb(函数指针类型)
描述:当新连接到来时,进行回调的函数。如果此函数为 NULL,则监听器按被禁用运行,直到函数被设置为非 NULL 值。

ptr:

类型:void*
描述:提供给回调函数的参数指针。通常用于传递一些上下文信息给回调函数。

flags:

类型:unsigned
描述:属性标志位,可以取多个值,用于控制监听器的行为。例如,LEV_OPT_REUSEABLE 表示端口复用,LEV_OPT_CLOSE_ON_FREE 表示释放资源时自动关闭套接字。

backlog:

类型:int
描述:类似于标准 listen() 函数的 backlog 参数,用于指定未完成连接队列的最大长度。如果设置为 -1,则使用默认值。

sa:

类型:const struct sockaddr*
描述:要绑定到的地址的套接字地址结构。这通常是一个指向 sockaddr_in 或 sockaddr_in6 结构体的指针,具体取决于你想要监听的 IP 版本(IPv4 或 IPv6)。

socklen:

类型:int
描述:sa 参数指向的套接字地址结构的字节长度。

返回值

如果成功,返回一个指向新分配的 evconnlistener 对象的指针。
如果失败,返回 NULL。

注意事项

使用 evconnlistener_new_bind 时,Libevent 会自动完成 socket()、bind() 和 listen() 的系统调用,并设置 accept() 的回调函数。
你不需要手动设置套接字为非阻塞模式,因为 Libevent 会为你处理这些细节。
如果想要监听所有可用的网络接口(即 INADDR_ANY),可以在 sockaddr_in 结构体的 sin_addr 字段中设置其 s_addr 成员为 0。

示例

// 假设已经包含了必要的头文件和设置了相应的变量  
struct sockaddr_in sin;  
memset(&sin, 0, sizeof(sin));  
sin.sin_family = AF_INET;  
sin.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有网络接口  
sin.sin_port = htons(8080); // 监听 8080 端口  
  
struct evconnlistener* listener = evconnlistener_new_bind(  
    base,  
    callback_function,  // 自定义的回调函数  
    NULL,  
    LEV_OPT_REUSEABLE,  // 设置端口复用  
    -1,                 // 使用默认的 backlog 值  
    (struct sockaddr*)&sin,  
    sizeof(sin)  
);  
if (!listener) {  
    // 处理错误  
}

sockaddr_in 是 IPv4 网络编程中用于表示套接字地址的结构体。它定义在 <netinet/in.h> 头文件中,并通常与套接字函数(如 bind(), connect(), accept() 等)一起使用。

sockaddr_in 结构体的定义可能因操作系统和编译器而异,但大致如下:

struct sockaddr_in {  
    short            sin_family;   // 地址族,通常为 AF_INET  
    unsigned short   sin_port;     // 端口号,网络字节序  
    struct in_addr   sin_addr;     // IPv4 地址  
    char             sin_zero[8];  // 填充字段,未使用,必须设置为 0  
};  
  
// in_addr 是一个结构体,通常只包含一个成员,用于表示 32 位的 IPv4 地址  
struct in_addr {  
    unsigned long s_addr;  // IPv4 地址,网络字节序  
};

解析 sockaddr_in

sin_family:

这是一个地址族字段,通常设置为 AF_INET(在 <sys/socket.h> 中定义)以表示这是一个 IPv4 地址。

sin_port:

这是一个 16 位的端口号字段,以网络字节序(大端字节序)存储。在使用之前,你可能需要使用 htons() 函数(host to network short)将其从主机字节序转换为网络字节序,反之亦然,使用 ntohs() 函数。

sin_addr:

这是一个 in_addr 结构体,用于存储 32 位的 IPv4 地址。in_addr 结构体通常只包含一个 unsigned long 类型的 s_addr 字段。你可以使用 inet_pton() 函数(presentation to network)将点分十进制表示的 IP 地址(如 “192.168.1.1”)转换为网络字节序的 in_addr 结构体,或使用 inet_ntoa() 函数(但请注意,inet_ntoa() 不是线程安全的)将其转换回点分十进制表示。

sin_zero:

这是一个填充字段,用于确保 sockaddr_in 结构体的大小与 sockaddr 结构体的大小相同。你应该始终将其设置为 0。

示例

以下是一个简单的示例,展示了如何设置一个 sockaddr_in 结构体:

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
  
int main() {  
    struct sockaddr_in server_addr;  
  
    // 设置地址族为 IPv4  
    server_addr.sin_family = AF_INET;  
  
    // 设置端口号为 8080(网络字节序)  
    server_addr.sin_port = htons(8080);  
  
    // 设置 IP 地址为 192.168.1.1(网络字节序)  
    if (inet_pton(AF_INET, "192.168.1.1", &server_addr.sin_addr) <= 0) {  
        perror("inet_pton");  
        exit(EXIT_FAILURE);  
    }  
  
    // sin_zero 必须设置为 0  
    memset(server_addr.sin_zero, 0, sizeof(server_addr.sin_zero));  
  
    // 现在你可以使用 server_addr 进行网络编程了  
    // ...  
  
    return 0;  
}
  • 21
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flos chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值