From libuv to epoll, from libuv to epoll
Introduction
This blog post may be a bit watery, mainly focusing on the learning process and understanding of libuv. It's a bit complicated to talk about the methods. Let's get started.
First, we will introduce githup. This tool is particularly useful. Code hosting. If you don't use FQ, you may have some cards. But you should try it. Here, let's talk about githup.
It is too important to improve the Code level. There is also a forum to Solve the Problem stackoverflow http://stackoverflow.com /.
It's really embarrassing.
Complimentary
Githup simple tutorial, don't thank http://www.nowcoder.com/courses/2
There is also a forum in China that is extremely demanding. If you have nb, you can install it. Take one of the posts as an example.
Zhihu epoll discussion http://www.zhihu.com/question/21516827
The introduction is over.
Preface
Now let's start to talk about libuv. This is a cross-platform network library, which is a C library. It has more efficient programming than other similar Network Libraries, so we don't need to consider too much details.
Is node. the underlying layer of js. I learned for a week or two and found that the function is quite powerful. good versatility. but I always feel a little disgusting. I will talk about it later. in general, it is very good,
But do not like.
Next I will share with you how to learn about libuv. First, you should go to the official website to download the libuv code.
Libuv githup source code https://github.com/libuv/libuv at this time you need to compile and install on your linux.
The procedure is readme. md.
At this time, you will surely fail. how can this problem be solved. go to stackoverflow to find the answer. google search can solve this problem. one problem I encountered was gateway timeout. modify the gateway. try it by yourself to improve the speed.
Install the SDK for a long time. Let's test it. Take the libuv Chinese version as an example.
# Include <stdio. h> # include <string. h> # include <uv. h> uv_tty_t g_tty; uv_timer_t g_tick; int g_width, g_height, g_pos; static void _ update (uv_timer_t * req) {uv_write_t wreq; char data [64]; const char * msg = "Hello TTY"; uv_buf_t buf; buf. base = data; buf. len = sprintf (data, "\ 033 [2J \ 033 [H \ 033 [% dB \ 033 [% luC \ 033 [42; 37 m % s", g_pos, (g_width-strlen (msg)/2, msg); uv_write (& wreq, (uv_stream_t *) & g_tty, & buf, 1, NULL ); if (++ g_pos> g_height) {uv_tty_reset_mode (); uv_timer_stop (& g_tick) ;}// the main function checks int main (void) {uv_loop_t * loop = uv_default_loop (); uv_tty_init (loop, & g_tty, 1, 0); uv_tty_set_mode (& g_tty, 0); if (uv_tty_get_winsize (& g_tty, & g_width, & g_height )) {puts ("cocould not get TTY information"); uv_tty_reset_mode (); return 1;} printf ("Width % d, height % d \ n", g_width, g_height ); uv_timer_init (loop, & g_tick); uv_timer_start (& g_tick, _ update, 200,200); return uv_run (loop, UV_RUN_DEFAULT );}
During the test, you will see the animation. Console Animation
gcc -g -Wall -o uvtty.c uvtty.c -luv
Running is
Run the command to see that Hello TTY will keep moving down to know if it is moving to the end.
So far, it indicates that the basic environment of libuv is good, and it can be developed. Here we are playing a big show. A few Chinese people have translated a book developed by libuv,
Address
Libuv Chinese programming take away Thank http://www.nowx.org/uvbook/
Here, I would like to extend my gratitude to others for their achievements. Without them, we can only wait for a closed door to build a car. Foreign technology is at least five years ahead of China.
You need to check the following code when reading the above books.
Libuv Chinese programming DEMO code https://github.com/nikhilm/uvbook/tree/master/code
You need to read at least that book. If you have any problems, refer to the libuv source code. You need to repeat the demo code in the book. At least libuv is not unfamiliar.
I have typed all the exercises above, copied them, optimized them, and modified them.
Here, the idea of libuv learning is basically fixed. It is to write code.
Okay. Let's give you a brief description of libuv.
1. The best way to learn libuv is to understand the source code .........
(The source code is understandable and cannot be written yet .)
2. libuv network development is indeed simple, and the network layer can be-lines of code, but it provides a thread pool for example, the timer together the source code looks a little more difficult, cross-platform terminal control.
3. The development of global variables and hidden headers in libuv is too rampant .....
All in all, C development is not on the wheel once and for all. Otherwise, it will become a standard library. Both have advantages and disadvantages. Look at your own application fields. libuv, which is strongly recommended for viewing Network Libraries, is better than libevent and libuv.
Encapsulation is easy to write. I 've forgotten it for a long time ........
It's almost over here. The best thing is thinking and design ......
Body
Here I thought about some network libraries, but they still cannot be encapsulated. I feel the foundation is still poor. it's too mysterious to start with the basics. this is equivalent to epoll. start with epoll.
For socket basic development, please refer to my blog http://www.cnblogs.com/life2refuel/p/5240175.html
I briefly explained socket development and finally gave an epoll case.
Epoll actually has four functions.Man epoll_createYou can check it on linux. for how to get started with it, search for 10 good epoll blog posts.
It will be developed. the others are gradually upgraded. here we will not elaborate on what epoll is. let's take a simple example to help you get started. the essence of epoll is that the upper layer of the operating system's polling detection notification can be used.
Example 1 monitoring stdin Input
# Include <stdio. h> # include <stdlib. h> # include <unistd. h> # include <sys/epoll. h> # define _ INT_BUF (255) // epoll helloworld exercise int main (void) {int epfd, nfds, I, len; char buf [_ INT_BUF]; struct epoll_event ev; epfd = epoll_create (1); // listen to a descriptor and. stdin ev. data. fd = STDIN_FILENO; ev. events = EPOLLIN; // use the default <condition to trigger epoll_ctl (epfd, EPOLL_CTL_ADD, STDIN_FILENO, & ev); // 10 indicates waiting 30 s, exit for (;) {nfds = epo Ll_wait (epfd, & ev, 1,-1); for (I = 0; I <nfds; ++ I) {if (ev. data. fd = STDIN_FILENO) {len = read (STDIN_FILENO, buf, sizeof buf-1); buf [len] = '\ 0'; printf ("% s ", buf) ;}}// impose an end condition. if (random () % 100> = 90) break;} puts ("Epoll Hello world is end! "); // Close (epfd); return 0;} should be released as long as it is a file descriptor ;}
// Compile gcc-g-Wall-o epoll_stdin.out epoll_stdin.c
The running result is
When the user inputs the data, read the output again.
Let's talk about the class vi configuration we use.
In the root directory, touch. vimrc writes the following information
"Set Default decoding set fenc = UTF-8" sets the default Character set fencs = UTF-8, usc-bom, euc-jp, gb18030, gbk, gb2312, cp936 "to disable the compatibility mode of VI, using VIM only, vi is still difficult to set nocompatible "display row number" vim uses automatic alignment, that is to say, apply the alignment format of the current row to the next line set autoindent. "based on the alignment format above, smart selection Alignment Method set smartindent "set the tab key to 4 spaces set tabstop = 4" set to use four spaces when lines are staggered set shiftwidth = 4 "set during editing, in the lower right corner, the status line set ruler at the cursor position is displayed. "set incremental search, in this case, the smart set incsearch "highlighted matching brackets set showmatch" matching brackets are highlighted (in 1/10 s) set ignorecase "case-insensitive set matchtime = 1" highlighted syntax on is ignored during search
It is a good combination.
Finally, let's look at a simple epoll + pthread case. Sometimes we feel that starting from the bottom layer, we will always be more difficult than water.
# Include <stdio. h> # include <stdlib. h> # include <errno. h> # include <string. h> # include <pthread. h> # include <unistd. h> # include <fcntl. h> # include <netinet/in. h> # include <arpa/inet. h> # include <sys/types. h> # include <sys/time. h> # include <sys/resource. h> # include <sys/socket. h> # include <sys/epoll. h> // 4.0 the error message is printed on the console. fmt must be a macro enclosed in double quotation marks # define CERR (fmt ,...) \ fprintf (stderr, "[% s: % d] [error % d: % s]" fmt "\ r \ n ",\__ FILE __, _ func __, _ LINE __, errno, strerror (errno), ##__ VA_ARGS _) // print the error message on the 4.1 console and exit, t. Similarly, fmt must be a String constant enclosed by "" # define CERR_EXIT (fmt ,...) \ CERR (fmt, ##__ VA_ARGS _), exit (EXIT_FAILURE) // 4.2 check a line of code and test result # define IF_CHECK (code) \ if (code) <0) \ CERR_EXIT (# code) // The listening queue is twice less than the listening file descriptor epoll # define _ INT_EPL (8192) # define _ INT_BUF (1024) # define _ INT_PORT (8088) # define _ STR_IP "127.0.0.1" // data to be sent # define _ STR_MSG" HTTP/1.0 200 OK \ r \ nContent-type: text/plain \ r \ nI am here, heoo... \ r \ n "// void * message (void * arg) function executed by the thread; // sets the file descriptor to be non-blocking, 0 extern inline int setnonblocking (int fd) is returned if the setting is successful; // enable the int openserver (const char * ip, unsigned short port) for server listening; // The main logic, enable thread and epoll listening int main (int argc, char * argv []) {int nfds, I, cfd; struct sockaddr_in caddr; socklen_t clen = sizeof caddr; pthread_t tid; struct epoll_event e V, evs [_ INT_EPL]; int sfd = openserver (_ STR_IP, _ INT_PORT); int efd = epoll_create (_ INT_EPL); if (efd <0) {close (sfd); CERR_EXIT ("epoll_create % d is error! ", _ INT_EPL);} ev. events = EPOLLIN | EPOLLET; ev. data. fd = sfd; if (epoll_ctl (efd, EPOLL_CTL_ADD, sfd, & ev) <0) {close (efd); close (sfd); CERR_EXIT ("epoll_ctl is error! ");} // Wait for the OS notification file descriptor to determine whether the descriptor can be _ startloop: if (nfds = epoll_wait (efd, evs, _ INT_EPL,-1 )) <= 0) {if (nfds = 0 | errno = EINTR) goto _ startloop; // an error occurs, CERR ("epoll_wait is error nfds = % d. ", nfds); goto _ endloop;} // The event is correct for (I = 0; I <nfds; ++ I) {if (evs [I]. data. fd = sfd) {// new connection // clen for input and output parameters cfd = accept (sfd, (struct sockaddr *) & caddr, & clen ); if (cfd <0) {CERR ("accept is erro R sfd = % d. ", sfd); goto _ startloop; // continue other services} CERR (" [% s: % d] happy connected here. ", inet_ntoa (caddr. sin_addr), htons (caddr. sin_port); // register the new file descriptor over ev. events = EPOLLIN | EPOLLET; ev. data. fd = cfd; setnonblocking (cfd); if (epoll_ctl (efd, EPOLL_CTL_ADD, cfd, & ev) <0) {CERR ("epoll_ctl add cfd: % d error. ", cfd); // there is a problem that cfd is not released. Please release goto _ endloop;} else {// here it is readable/ /The speed is too fast, and there are also data exceptions. if (pthread_create (& tid, NULL, message, & evs [I]. data. fd) <0) {CERR ("pthread_create is error! "); Goto _ endloop ;}} goto _ startloop ;__ endloop: CERR (" epoll server is error, to exit... "); close (efd); close (sfd); return 0;} // void * message (void * arg) of the function executed by the thread {char buf [_ INT_BUF]; int cfd = * (int *) arg, rt; // get the file descriptor // set the thread separation attribute and recycle pthread_detach (pthread_self (); // read data cyclically, for (;) {rt = read (cfd, buf, _ INT_BUF-1); if (rt <0) {if (errno = EINTR) // signal interruption continues continue; // when no data can be read or written in the buffer zone due to non-blocking mode, the EAGAIN signal if (errno = EAGAIN) {rt = 1 is triggered; // indicates that the client connection has not broken the break;} // the following error occurs: CERR ("read cfd = % d, is rt = % d. ", cfd, rt); break;} // you need to continue reading client data if (rt = _ INT_BUF-1) continue; // The following indicates that the client has disabled CERR ("read end cfd = % d. ", cfd); break;} // send data to the client if (rt> 0) {// send information to the client, multiple '\ 0' write (cfd, _ STR_MSG, strlen (_ STR_MSG) + 1);} // after the service is processed, close the connection with the server (cfd); return NULL ;} // if the file descriptor is set to non-blocking, 0 inline int setnonblocking (int fd) {int zfd = fcntl (fd, F_GETFD, 0); if (fcntl (fd, fd, f_SETFL, zfd | O_NONBLOCK) <0) {CERR ("fcntl F_SETFL fd: % d, zfd: % d. ", fd, zfd); return-1;} return 0;} // enable server listening int openserver (const char * ip, unsigned short port) {int sfd, opt = require; struct sockaddr_in saddr = {AF_INET}; struct rlimit rt = {_ INT_EPL, _ INT_EPL}; // sets the maximum number of files opened by each process IF_CHECK (setrlimit (RLIMIT_NOFILE, & rt); // enable the socket listener IF_CHECK (sfd = socket (PF_INET, SOCK_STREAM, 0); // set port multiplexing. opt can be abbreviated to 1, as long as it is not 0 IF_CHECK (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, & opt, sizeof opt); // you can set the bind binding port saddr. sin_addr.s_addr = inet_addr (ip); saddr. sin_port = htons (port); IF_CHECK (bind (sfd, (struct sockaddr *) & saddr, sizeof saddr); // start to listen to IF_CHECK (listen (sfd, _ INT_EPL> 1); // at this time, the service starts and listens for return sfd ;}
This server monitors the client connection and sends messages to the client
-Lpthread must be added during compilation.
The running result is as follows:
Client
The above epoll case has the opportunity to learn it on your own. time-consuming. but nothing is more interesting if you don't learn it. here we have the opportunity to continue sharing the basics used in development.
Model. network Development is really difficult, with too many details, but it is also easy to be a routine... I hope this article will provide some libuv learning methods and epoll basic cases for you to hear at least
, With the force of installation.
Postscript
Errors are inevitable. If you have any questions, try again ....