libevent实践06:监听TCP服务器

这篇具有很好参考价值的文章主要介绍了libevent实践06:监听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:事件集合

 evconnlistener_cb:cb是call back的缩写,就是回调函数定义如下:

typedef void (*evconnlistener_cb)(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *);

ptr:传递给cb的参数

flags:属性标志位,可取值9个(掰手指头数的),下面是9个取值的宏定义,在evconnlistener_new_bind函数源码中也可以看出来。

/** Flag: Indicates that we should not make incoming sockets nonblocking
 * before passing them to the callback. */
#define LEV_OPT_LEAVE_SOCKETS_BLOCKING	(1u<<0)
/** Flag: Indicates that freeing the listener should close the underlying
 * socket. */
#define LEV_OPT_CLOSE_ON_FREE		(1u<<1)
/** Flag: Indicates that we should set the close-on-exec flag, if possible */
#define LEV_OPT_CLOSE_ON_EXEC		(1u<<2)
/** Flag: Indicates that we should disable the timeout (if any) between when
 * this socket is closed and when we can listen again on the same port. */
#define LEV_OPT_REUSEABLE		(1u<<3)
/** Flag: Indicates that the listener should be locked so it's safe to use
 * from multiple threadcs at once. */
#define LEV_OPT_THREADSAFE		(1u<<4)
/** Flag: Indicates that the listener should be created in disabled
 * state. Use evconnlistener_enable() to enable it later. */
#define LEV_OPT_DISABLED		(1u<<5)
/** Flag: Indicates that the listener should defer accept() until data is
 * available, if possible.  Ignored on platforms that do not support this.
 *
 * This option can help performance for protocols where the client transmits
 * immediately after connecting.  Do not use this option if your protocol
 * _doesn't_ start out with the client transmitting data, since in that case
 * this option will sometimes cause the kernel to never tell you about the
 * connection.
 *
 * This option is only supported by evconnlistener_new_bind(): it can't
 * work with evconnlistener_new_fd(), since the listener needs to be told
 * to use the option before it is actually bound.
 */
#define LEV_OPT_DEFERRED_ACCEPT		(1u<<6)
/** Flag: Indicates that we ask to allow multiple servers (processes or
 * threads) to bind to the same port if they each set the option. 
 * 
 * SO_REUSEPORT is what most people would expect SO_REUSEADDR to be, however
 * SO_REUSEPORT does not imply SO_REUSEADDR.
 *
 * This is only available on Linux and kernel 3.9+
 */
#define LEV_OPT_REUSEABLE_PORT		(1u<<7)
/** Flag: Indicates that the listener wants to work only in IPv6 socket.
 *
 * According to RFC3493 and most Linux distributions, default value is to
 * work in IPv4-mapped mode. If there is a requirement to bind same port
 * on same ip addresses but different handlers for both IPv4 and IPv6,
 * it is required to set IPV6_V6ONLY socket option to be sure that the
 * code works as expected without affected by bindv6only sysctl setting in
 * system.
 *
 * This socket option also supported by Windows.
 */
#define LEV_OPT_BIND_IPV6ONLY		(1u<<8)

backlog:设置监听队列的大小,同listen函数的第二个参数。

int listen(int s, int backlog);

sa:IP和端口,同bind函数的第二个参数

socklen:结构体长度,同bind函数的第三个参数

int bind(int sockfd, struct sockaddr *sa, socklen_t socklen)

返回值:struct evconnlistener *

从源码简单分析可知 evconnlistener_new_bind内部实现了创建socket,绑定IP地址和端口,最后监听socket。

/**
   Allocate a new evconnlistener object to listen for incoming TCP connections
   on a given address.

   @param base The event base to associate the listener with.
   @param cb A callback to be invoked when a new connection arrives. If the
      callback is NULL, the listener will be treated as disabled until the
      callback is set.
   @param ptr A user-supplied pointer to give to the callback.
   @param flags Any number of LEV_OPT_* flags
   @param backlog Passed to the listen() call to determine the length of the
      acceptable connection backlog.  Set to -1 for a reasonable default.
   @param addr The address to listen for connections on.
   @param socklen The length of the address.
 */
struct evconnlistener *
evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
    void *ptr, unsigned flags, int backlog, const struct sockaddr *sa,
    int socklen)
{
	struct evconnlistener *listener;
	evutil_socket_t fd;
	int on = 1;
	int family = sa ? sa->sa_family : AF_UNSPEC;
	int socktype = SOCK_STREAM | EVUTIL_SOCK_NONBLOCK;

	if (backlog == 0)
		return NULL;

	if (flags & LEV_OPT_CLOSE_ON_EXEC)
		socktype |= EVUTIL_SOCK_CLOEXEC;

	fd = evutil_socket_(family, socktype, 0);
	if (fd == -1)
		return NULL;

	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on))<0)
		goto err;

	if (flags & LEV_OPT_REUSEABLE) {
		if (evutil_make_listen_socket_reuseable(fd) < 0)
			goto err;
	}

	if (flags & LEV_OPT_REUSEABLE_PORT) {
		if (evutil_make_listen_socket_reuseable_port(fd) < 0)
			goto err;
	}

	if (flags & LEV_OPT_DEFERRED_ACCEPT) {
		if (evutil_make_tcp_listen_socket_deferred(fd) < 0)
			goto err;
	}

	if (flags & LEV_OPT_BIND_IPV6ONLY) {
		if (evutil_make_listen_socket_ipv6only(fd) < 0)
			goto err;
	}

	if (sa) {
		if (bind(fd, sa, socklen)<0)
			goto err;
	}

	listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd);
	if (!listener)
		goto err;

	return listener;
err:
	evutil_closesocket(fd);
	return NULL;
}

实例:监听服务器

#include <sys/types.h>
#include <event2/event-config.h>
#include <event2/listener.h>
#include <stdio.h>
#include <event.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%d $$ " format "\n" \
,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

/*

*/

void server_evconnlistener_cb(struct evconnlistener *listener, evutil_socket_t new_client, struct sockaddr *addr, int socklen, void *arg)
{
    struct sockaddr_in *paddr = (struct sockaddr_in *)addr;
    DEBUG_INFO("a new client fd = %d",new_client);
    //char *inet_ntoa(struct in_addr in);
    DEBUG_INFO("ip = %s,port = %d",inet_ntoa(paddr->sin_addr),ntohs(paddr->sin_port));
}

int main(int argc, char **argv){
    struct event_base *base;
    struct evconnlistener *listener;
    struct sockaddr_in addr;

    base = event_base_new();
    if(base == NULL){
        DEBUG_INFO("Couldn't create event_base");
        exit(-1);
    }

    addr.sin_family = AF_INET;
    // addr.sin_addr.s_addr = INADDR_ANY;
    // addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    // addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_addr.s_addr = inet_addr("192.168.0.11");
    addr.sin_port = htons(6666);

    listener = evconnlistener_new_bind(
        base,
        server_evconnlistener_cb,
        NULL,//传给cb的参数,本例中就是server_evconnlistener_cb
        LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
        5,//listen的第二个参数
        (struct sockaddr*)&addr,//bind的第二个参数
        sizeof(addr) //bind的第三个参数
    );
    if(listener == NULL){
        DEBUG_INFO("evconnlistener_new_bind error");
        exit(-1);
    }
    //开始监听集合中的事件
    event_base_dispatch(base);
    evconnlistener_free(listener);
    event_base_free(base);
    DEBUG_INFO("bye bye");
    return 0;
}

测试:

运行程序,使用网络调试助手连接服务器的6666端口

libevent实践06:监听TCP服务器,linux 应用,服务器,tcp/ip,网络,libevent

程序输出信息:

libevent实践06:监听TCP服务器,linux 应用,服务器,tcp/ip,网络,libevent 

实验分析:

从调试信息可知,输出信息中包含新客户端的文件描述符,客户端的IP地址和客户端的端口号。 文章来源地址https://www.toymoban.com/news/detail-519736.html

小结

到了这里,关于libevent实践06:监听TCP服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • libevent高并发网络编程 - 04_libevent实现http服务器

    链接: C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂 在libevent中,HTTP的实现主要是通过 evhttp 模块来完成的。 evhttp 提供了一个高层次的HTTP服务器接口,可以处理HTTP请求并发送HTTP响应。 在源码中,libevent的HTTP协议处理主要是通过 evhttp 模块来完成的。

    2024年02月15日
    浏览(35)
  • jmeter 在linux服务器中执行性能测试、监听服务器资源指标

    下载apache-jmeter-5.5文件; 下载ServerAgent-2.2.3文件; 解压apache-jmeter-5.5文件;(需先安装java环境) 找到apache-jmeter-5.5apache-jmeter-5.5bin目录,运行 ApacheJMeter.jar 创建 测试计划 、 线程组 、 HTTP请求 及各类监听组件; 保存脚本为 xxx.jmx 文件。 将apache-jmeter-5.5.tgz 压缩包上传至服务器,

    2024年02月09日
    浏览(73)
  • TCP客户端及服务器端开发实践

    ① TCP客户端应用程序开发 ② TCP服务器端应用程序开发 客户端程序是指运行在用户设备上的程序,服务端程序是指运行在服务器设备上的程序,专门为客户端提供数据服务。那如何记忆呢? 主动发起建立连接请求的是客户端程序,等待接受连接请求的是服务端程序。 开发流

    2024年04月09日
    浏览(52)
  • Qt实践:TCP服务器和客户端的设计

    Qt:5.12.2 Qt Creator:4.11.1 通信方式:TCPIP 语言:C++ 客户端的界面UI包含服务器IP、服务器端口、以及一些简单的功能,数据可选ASCLL及HEX格式。当未与服务器建立连接时,该客户端的部分控件设置为禁用。 \\\'getIp()\\\'函数可以根据不同的操作系统获取本地 IP 地址。在 Windows 系统下

    2024年02月03日
    浏览(42)
  • 查看服务器的监听端口(Windows、Linux、MacOS)

    打开命令行窗口(Windows)或终端(Linux/MacOS)。 输入以下命令: 按下回车键,将会列出所有正在监听的端口及其对应的进程ID。 如果需要查看某个特定端口的监听情况,可以使用以下命令: 其中,将“端口号”替换为需要查看的端口号。 如果需要查看进程ID对应的进程名称

    2024年02月08日
    浏览(58)
  • 基于STM32F103,利用W5500芯片实现TCP客户端连接TCP服务器的实践

    尊敬的读者,您好!在这篇文章中,我们将一起深入了解如何使用STM32F103和W5500芯片,实现TCP客户端连接到TCP服务器的过程。在详细的步骤中,我们不仅会给出相关的理论介绍,同时也会提供实战代码以供大家参考和学习。希望大家在阅读完这篇文章后,能够有所收获。 实战

    2024年02月11日
    浏览(34)
  • tcp连接阿里云linux服务器失败

    原因: 自己程序bind的是127.0.0.1 应该改成 bind 阿里云的私网地址 client连接的是阿里云公网地址 参考: 阿里云服务器,客户端socket无法连接的问题 - 爱码网 排查过程记录: 1,安全组设置:有正常设置 2,防火墙有没有允许端口:已经允许 root@iZwz9hty12mlm1wlg0jzn0Z:~# ufw allow 808

    2024年02月06日
    浏览(39)
  • Linux 服务器 TCP 连接数参数调整

    服务器 es 或增加 nginx 要想增加处理能力,调整 TCP 连接数可以通过修改操作系统的TCP参数来实现,以下是具体操作步骤,在此做下记录: 1、查看系统TCP连接资源命令 2、调整操作系统的最大连接数限制           /etc/sysctl.conf 文件         然后运行以下命令使设置生

    2024年04月09日
    浏览(54)
  • Linux socket 搭建TCP服务器(C语言)

    ​ 在标题之前,先提几个问题,方便下次查看理解。 什么是TCP TCP服务器需要用到哪些函数 如何简单的搭建一个TCP服务器 ​ TCP 是一种传输层协议,可以提供可靠的数据传输服务。它是面向连接的,具有可靠性、流量控制、拥塞控制以及双工通信的特点。 1. socket ​ socket 作

    2024年04月17日
    浏览(38)
  • linux服务器 tcp高并发压测需要设置项

    linux服务器部署了一个tcp服务,需要进行并发压力测试  看看服务器能支持多少个tcp长连接   预计会有50w个连接 需要设置linux 不然是无法支持这么多连接的   如果达到这个值是无法建立新连接的  报错信息一般为  too many open files   1 ,  fs.file-max linux系统能打开的文件句柄

    2024年04月10日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包