恋恋风辰的个人博客


  • Home

  • Archives

  • Categories

  • Tags

  • Search

libevlearn

Posted on 2017-08-07 | In 网络编程

最近自学libevent事件驱动库,参考的资料为libevent2.2版本以及张亮提供的《Libevent源码深度剖析》,参考资料: http://blog.csdn.net/sparkliang/article/details/4957667, libevent好处之类的就不赘述了,libevent和libiop,redis等一样都是采用事件回调机制,这种模式被称作Reactor模式。正常事件处理流程是应用程序调用某个接口触发某个功能,而Reactor模式需要我们将这些接口和宿主指针(谁调用这些接口)注册在Reactor,在合适的时机Reactor使用宿主指针调用注册好的回调函数。

一: Reactor基本知识

Reactor 模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:
1)响应快,不必为单个同步时间所阻塞,虽然 Reactor 本身依然是同步的;
2)编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销;
3)可扩展性,可以方便的通过增加 Reactor 实例个数来充分利用 CPU 资源;
4)可复用性, reactor 框架本身与具体事件处理逻辑无关,具有很高的复用性;
Reactor模式框架
https://cdn.llfc.club/reactorlib.png

Read more »

windows环境libevent搭建和demo分析

Posted on 2017-08-07 | In 网络编程

libevent框架之前有做过分析,这次是谈谈如何将libevent搭建在vs工作环境下,并且编写一个demo进行测试。测试过程中会再一次带大家分析消息是怎么传递的。我的libevent版本libevent-2.0.22-stable,用对应的vs命令工具进入该目录

Read more »

libevent文档学习(一)多线程接口和使用

Posted on 2017-08-07 | In 网络编程

参考libevent官方提供的文档: http://www.wangafu.net/~nickm/libevent-book/Ref1_libsetup.html

这一篇主要翻译libevent多线程的使用接口和文档。

As you probably know if you’re writing multithreaded programs, it isn’t always safe to access the same data from multiple threads at the same time.

Libevent structures can generally work three ways with multithreading.

Some structures are inherently single-threaded: it is never safe to use them from more than one thread at the same time.

Some structures are optionally locked: you can tell Libevent for each object whether you need to use it from multiple threads at once.

Some structures are always locked: if Libevent is running with lock support, then they are always safe to use from multiple threads at once.

当你编写多线程程序的时候,多个线程访问同一块数据并不安全。对于多线程libevent通常采取以下三种方式工作,

1 一些结构内不是单线程的,多线程同时访问这个结构是不安全的。

2一些结构内部是选择性加锁的,你需要通知libevent,对于每个对象你是否采用多线程的方式使用它。

3一些结构总是加锁的,如果libevent设置了加锁的模式,采用多线程方式是安全的。

To get locking in Libevent, you must tell Libevent which locking functions to use. You need to do this before you call any Libevent function

that allocates a structure that needs to be shared between threads.

If you are using the pthreads library, or the native Windows threading code, you’re in luck. There are pre-defined functions that will set

Libevent up to use the right pthreads or Windows functions for you.

如果要使用libevent多线程锁的功能,需要开辟一个线程共享的结构,如果您使用windows或者linux提供的pthread库,libevent已经定义好了。

1
2
3
4
5
6
7
8
#ifdef WIN32
int evthread_use_windows_threads(void);
#define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
#endif
#ifdef _EVENT_HAVE_PTHREADS
int evthread_use_pthreads(void);
#define EVTHREAD_USE_PTHREADS_IMPLEMENTED
#endif

libevent针对win32平台定义了evthread_use_windows_threads,

libevent针对Linux thread库 定义了evthread_use_pthreads

evthread_use_pthread函数是这样的

Read more »

libevent学习文档(二)eventbase相关接口和参数

Posted on 2017-08-07 | In 网络编程

Setting up a default event_base

The event_base_new() function allocates and returns a new event base with the default settings. It examines the environment variables and returns a pointer to a new event_base.

If there is an error, it returns NULL.

When choosing among methods, it picks the fastest method that the OS supports.

event_base_new()创建默认event_base,他检测环境变量并且返回一个指向新的event_base的指针。

当调用方法时,选择操作系统支持的做快速的方法。

Interface

struct event_base *event_base_new(void);
Setting up a complicated event_base

If you want more control over what kind of event_base you get, you need to use an event_config. An event_config is an opaque structure that holds information about your preferences for an event_base. When you want an event_base, you pass the event_config to event_base_new_with_config().

想要创建指定类型的event_base,需要使用event_config,event_config是不透明的结构体,保存了您创建event_base时需要的特性。

用户调用event_base_new_with_config创建特殊类型的event_base

Read more »

libevent学习文档(三)working with event

Posted on 2017-08-04 | In 网络编程

Events have similar lifecycles. Once you call a Libevent function to set up an event and associate it with an event base, it becomes initialized. At this point, you can add, which makes it pending in the base. When the event is pending, if the conditions that would trigger an event occur (e.g., its file descriptor changes state or its timeout expires), the event becomesactive, and its (user-provided) callback function is run. If the event is configured persistent, it remains pending. If it is not persistent, it stops being pending when its callback runs. You can make a pending event non-pending by deleting it, and you can add a non-pending event to make it pending again.

事件有相似的生命周期,一旦你调用libevent函数设置event和event_base关联后,event被初始化了。add这个事件会使它阻塞,当事件阻塞时,有触发事件的条件出现,事件会激活,回调函数会被调用。如果事件被设置为永久,它保持阻塞。如果不是永久,当事件的回调函数调用的时候就不阻塞了。可以通过删除一个事件使它由阻塞变为非阻塞。通过添加使它由非阻塞变为阻塞。

Read more »

Libevent学习笔记(四) bufferevent 的 concepts and basics

Posted on 2017-08-04 | In 网络编程

Bufferevents and evbuffers

Every bufferevent has an input buffer and an output buffer. These are of type “struct evbuffer”. When you have data to write on a bufferevent, you add it to the output buffer; when a bufferevent has data for you to read, you drain it from the input buffer.

每个bufferevents都会包含一个input的buffer和output的buffer,都是struct evbuffer类型, 如果你有数据想通过bufferevent发送,需要将数据放入output buffer里。如果要从bufferevent中读数据,

需要从input buffer里读取。

Callbacks and watermarks

Every bufferevent has two data-related callbacks: a read callback and a write callback. By default, the read callback is called whenever any data is read from the underlying transport, and the write callback is called whenever enough data from the output buffer is emptied to the underlying transport. You can override the behavior of these functions by adjusting the read and write “watermarks” of the bufferevent.

每一个bufferevent都有两个回调函数,一个读回调和一个写回调函数,默认情况下,只要从底层传输读取数据就回触发读回调函数,当output buffer中足够多的数据排出就会触发写回调函数。而我的理解是,这里的足够多,默认情况下是排空,

用户可以通过调整读写水位来达到控制这些函数触发。

Read more »

Libevent学习笔记(五) 根据例子学习bufferevent

Posted on 2017-08-04 | In 网络编程

libevent中提供了一个Hello-world.c 的例子,从这个例子可以学习libevent是如何使用bufferevent的。
这个例子在Sample中
https://cdn.llfc.club/bufferevent1.png
这个例子之前讲解过,这次主要看下bufferevent的使用。

Read more »

网络编程的一些错误总结

Posted on 2017-08-04 | In 网络编程

最近自己在写一套服务器框架,期间遇到很多问题,对于Linux或者windows出错情况下可以通过错误码获取错误信息。为了测试服务器性能,我在客户端开了2000个线程,这样每个线程都创建socket和服务器通信,连接15个线程,再后来的客户端线程connect过程中会失败,我另起了一个客户端进程进行连接,还是能连接15个过后才出现问题,初步可以排除服务器并没有达到连接上限,之后在linux上打印该错误码为111,查询意思为服务器拒绝客户端连接。查询相关资料是监听队列设置为5,只能接受一部分剩余的由于监听队列满了就被拒绝了。之后查询libevent和redis库的一些监听队列大小,设置为128较为合适,这次同样会出现一部分客户端连接失败,因为监听队列总是有限的,尽管如此,极限的情况下一秒同时连接500多个客户端还是没问题。

Read more »

网络编程一些常见问题总结

Posted on 2017-08-04 | In 网络编程

1 设置网络socket非阻塞:

1
2
u_long has = 1;
ioctl(m_sock, FIONBIO , &has);

这个函数很有可能返回success,却并没有设置成功。
windows对此有优化,对于linux版本应采用fcntl设置。

总结如下:

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
int
make_socket_nonblocking(sockfd fd)
{
#ifdef WIN32
{
u_long nonblocking = 1;
if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) {
cout << "fcntl failed, fd is : " << fd;

return -1;
}
}
#else
{
int flags;
if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) {
cout << "fcntl failed, fd is : " << fd;
return -1;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
cout << "fcntl failed, fd is : " << fd;
return -1;
}
}
#endif
return 0;
}
Read more »

ECONNRESET和WSAECONNRESET怎么产生的以及如何避免

Posted on 2017-08-04 | In 网络编程

ECONNRESET是linux环境网络编程产生的错误,错误码为104,

WSAECONNRESET是windows环境网络编程产生的错误,错误码为10054

两者产生的原因都一样,分以下几种情况:

1接收端recv或者read, 对端已经关闭连接,recv/read返回该错误

2 对端重启连接,还未建立连接

3 发送端已经断开连接,但是调用send会触发这个错误

第二点第三点都可以通过判断返回值解决,第一点在一些看似正常情况下也会触发该错误。比如对端close(fd),接收端调用recv并没有返回0,而是-1,打印错误码为104或

10054,按道理讲这种情况按照返回值为0处理是可以的,但是尽量将代码写的规范一些,避免不必要的错误。

Read more »
<1…34353637>

370 posts
17 categories
21 tags
RSS
GitHub ZhiHu
© 2025 恋恋风辰 本站总访问量次 | 本站访客数人
Powered by Hexo
|
Theme — NexT.Muse v5.1.3