Network Programming Using libevent

Source: Internet
Author: User

Network Programming Using libevent-(I)

 

After learning UNIX network programming in zookeeper, we know that there will be several solutions when dealing with multiple users:

  1. A new connection.fork()Produce a process processing.
  2. A new connection.pthread_create()Produce a thread processing.
  3. A new connection enters event-based array, and the main process processes all I/O in nonblocking mode.

These three methods all have their own shortcomings:

  1. Usefork()The cost of each connection is too high.
  2. The problem of using multi-thread is solved by thread-safe and deadlock, and the problem of memory-leak must be handled.
  3. The event-based method is difficult to implement in practice, especially when you notice that the event is generated, nonblocking is required, and buffering needs to be implemented, the memory-leak problem that multi-thread will encounter will be more serious here. In a multi-CPU system, there is no way to use all CPU resources.

Of course, they have their own solutions for the first two parties:

  1. Solution in poll mode: when a process processes a connection, it does not directly die, but zookeeper returns to the zookeeper processing of accept, however, in this case, the memory-leak problem occurs. For example, a person who uses this method usually adds "after processing n connections, it will die again by the parent process ."fork()One click New 」. The most famous example is Apache 1.3.
  2. Thread-safe issues can be written by yourself, or used directly by other thread-safe libraries. The memory-leak issue can be analyzed through the garbage collection library. This mode is used for thread MPM of Apache 2.0.

However, currently, highly efficient servers prefer event-based. On the one hand, there is no overhead caused by create process/thread, on the other hand, you do not need to pass through shared memory or mutex to submit data between different processes/threads.

However, the event-based Real-time operations are as follows:

  1. select()Andpoll()The efficiency is too slow, resulting in a high cost of determining "What events are generated" each time. This is supported by BSD.kqueue()Linux supportepoll()And Solaris support/dev/pollBut neither of these functions is standard. Therefore, it is necessary to change them on different platforms.
  2. Because it is nonblockingwrite()Orsend()When the time is reached, buffering is required.
  3. It cannot be used because it is nonblocking.fgets()Or other similar functions, so you need to engrave a nonblocking on your own.fgets(). However, the information received by the user cannot be recorded once.read()Orrecv()There is only one line, so you have to do buffering yourself.

In fact, these three things are handled by the libevent library.

In addition, it is worth noting that libevent uses 3-clause BSD license instead of GPL, so it does not want to open a program license (such as for commercial purposes) and other libraries. Network Programming Using libevent-(II)

 

Next, we will explain how to use libevent. For convenience, we will directly compile a very simple time server as an example: when you attempt to provide the time directly on the server end, the server end will end up waiting.

In these examples, I use FreeBSD 6.0 as the zookeeper platform, and libevent 1.1a as the event-based library and compile.gcc -I/usr/local/include -o timeserver timeserver.c -L/usr/local/lib -levent(If the libevent header and library are placed in/usr/includeAnd/usr/libCan omit these two numbers ).

The original program comes at the end of the article.

event_init()Represents the number of changes used to initialize libevent.

event_set(&ev, s, EV_READ | EV_PERSIST, connection_accept, &ev)SetsPut this file descriptionev(The first and second data records), and inform the event (the third dataEV_READ) Call at the time of productionconnection_accept()(Fourth Region ).evWhen the data volume goes in (the fifth data volume ).

TheEV_PERSISTThis indicates that when the call is in, do not remove this event (the upload queue is retained in the event queue ).connection_accept()Internalconnection_time()Program comparison.

Whileevent_add(&ev, NULL)IsevWait until the event queue is reached. The second parameter specifies the timeout time and is setNULLThis parameter is ignored.

Lastevent_dispatch()Indicates that the event loop is input. When any file description in the queue generates an event, the callback function will be executed.

This program is very rough, and we don't care about blocking in many places. When it starts, you can redirect to port 7000, and the following result appears: gslin @ NetNews [~] [3:14/W5] T 0 7000


gslin@netnews [~/work/C] [3:15/W3] t 0 7000
Trying 0.0.0.0...
Connected to 0.
Escape character is '^]'.
Fri Nov 25 03:15:10 2005
Connection closed by foreign host.

This is the most basic use. You canman eventSee the complete description.

This istimeserver.c:


#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <event.h>
#include <stdio.h>
#include <time.h>

void connection_time(int fd, short event, struct event *arg)
{
char buf[32];
struct tm t;
time_t now;

time(&now);
localtime_r(&now, &t);
asctime_r(&t, buf);

write(fd, buf, strlen(buf));
shutdown(fd, SHUT_RDWR);

free(arg);
}

void connection_accept(int fd, short event, void *arg)
{
/* for debugging */
fprintf(stderr, "%s(): fd = %d, event = %d./n", __func__, fd, event);

/* Accept a new connection. */
struct sockaddr_in s_in;
socklen_t len = sizeof(s_in);
int ns = accept(fd, (struct sockaddr *) &s_in, &len);
if (ns < 0) {
perror("accept");
return;
}

/* Install time server. */
struct event *ev = malloc(sizeof(struct event));
event_set(ev, ns, EV_WRITE, (void *) connection_time, ev);
event_add(ev, NULL);
}

int main(void)
{
/* Request socket. */
int s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
perror("socket");
exit(1);
}

/* bind() */
struct sockaddr_in s_in;
bzero(&s_in, sizeof(s_in));
s_in.sin_family = AF_INET;
s_in.sin_port = htons(7000);
s_in.sin_addr.s_addr = INADDR_ANY;
if (bind(s, (struct sockaddr *) &s_in, sizeof(s_in)) < 0) {
perror("bind");
exit(1);
}

/* listen() */
if (listen(s, 5) < 0) {
perror("listen");
exit(1);
}

/* Initial libevent. */
event_init();

/* Create event. */
struct event ev;
event_set(&ev, s, EV_READ | EV_PERSIST, connection_accept, &ev);

/* Add event. */
event_add(&ev, NULL);

event_dispatch();

return 0;
}

 

Network Programming Using libevent-(III)

 

There is no direct relationship between this secondary failover and network programming.

In batch nonblocking Network Program, buffering is usually handled, but it is not easy to understand, mainly becauseread()Orrecv()Without a security guarantee, you can increase the size of a row at a time.

The buffer library provided in the libevent can be used. The complete description is as follows:man eventYou can see that the most common application isevbuffer_add(),evbuffer_readline()The other functions can be used if they exist. When necessary, let's look at the usage of these functions.

Directly providelibevent-buff.cAs an example, check the result of the response and check the source code again:


#include <sys/time.h>
#include <event.h>
#include <stdio.h>

void printbuf(struct evbuffer *evbuf)
{
for (;;) {
char *buf = evbuffer_readline(evbuf);
printf("* buf = %p, the string = /"/e[1;33m%s/e[m/"/n", buf, buf);
if (buf == NULL)
break;
free(buf);
}
}

int main(void)
{
struct evbuffer *evbuf;

evbuf = evbuffer_new();
if (evbuf == NULL) {
fprintf(stderr, "%s(): evbuffer_new() failed./n", __func__);
exit(1);
}

/* Add "gslin" into buffer. */
u_char *buf1 = "gslin";
printf("* Add /"/e[1;33m%s/e[m/"./n", buf1);
evbuffer_add(evbuf, buf1, strlen(buf1));
printbuf(evbuf);

u_char *buf2 = " is reading./nAnd he is at home./nLast.";
printf("* Add /"/e[1;33m%s/e[m/"./n", buf2);
evbuffer_add(evbuf, buf2, strlen(buf2));
printbuf(evbuf);

evbuffer_free(evbuf);
}

 

 

Content Source: http://www.cublog.cn/u/5251/showart_270584.html

By the way recommended reference: http://unx.ca/log/category/libevent/

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.