Category: Uncategorized

  • Anti-Spam Log Update: Forwarding requests to email

    We are happy to announce a new function for the anti-spam log. This will make managing your records more convenient and functional.

    This function allows you to forward requests to email if you marked them as “Not Spam” and you will get a copy of a message on your email.

    To enable this option, go to website settings and mark the option “Send a copy of the Anti-Spam log to my email.”.

    We would like to thank our users for all the valuable feedback they’ve given us to improve the service.

    We welcome your feedback.
    CleanTalk Dashboard

    Download our WordPress Plugins:
    Anti-Spam by CleanTalk
    WordPress Security & Firewall by CleanTalk

  • Critical vulnerability in our Jomla anti-spam plugin

    Hello!

    We should inform you about a critical vulnerability in our anti-spam plugin. It allows anyone to know your admin email.

    We’ve made the new release for Joomla anti-spam plugin and you have to upgrade your CleanTalk Anti-Spam plugin.

    Please, follow the instruction here
    https://cleantalk.org/help/update-joomla3

    We are so sorry to cause this issue for you.

    Let us know if you have any questions.

  • A new online tool to automatically boost the best Facebook posts

    Over the past years, the demand for boosting Facebook posts has increased dramatically. With Facebook decreasing the organic reach continually, Facebook marketers need to pay for getting the desired reach and support engagement. In Facebook, you can no longer boost all new posts automatically. Neither you can set up rules that would select the posts that will be boosted.

    How Boosterberg Idea Originated

    Digital marketing agencies, Facebook marketers and marketing managers in organisations had to go to Ads Manager and boost each post manually by clicking the Boost Post button. This approach has taken a lot of time, and what is worse, they did not typically have enough information to decide what budget should they allocate and which posts should they boost. If they dug into the analytics and selected the best posts, it took them hours that could be spent more efficiently. To solve these problems, Boosterberg tool has been developed to take the burden away from Facebook marketers. It is an online tool, or SaaS software, that enables automatic boosting of Facebook posts. Once a user creates a new account, he will select a Facebook page and create a set of rules for it. Once they are saved, all new posts will be evaluated, and based on the criteria and their performance, they will or won’t be boosted. Everything is fully automated, and there is no need to check anything in Facebook Ads Manager anymore manually. There are basic or advanced settings to be used and several presets, and individual triggers are available to fine-tune the campaign. With Boosterberg, everyone can become a Facebook Advertising Pro. Moreover, Boosterberg has launched a Facebook Ads Academy for its fans and users, publishing the new expert advice on Facebook advertising practices written by Boosterberg staff members and other experts on social media marketing.

    Developing Boosterberg

    The development started approximately two years ago. At the beginning, two digital marketing agencies – PS:Digital and Kremsa Digital team up for this project to develop a platform that would help them to manage their Facebook clients more efficiently. PS: Digital was spending dozens of hours weekly just assessing the posts of their clients, selecting the best ones and boosting them. This is how the idea and specifications of Boosterberg came to live: We need to have a tool that automates this process of boosting Facebook posts. After searching on the market and finding nothing useful, a decision was made to develop an own tool. From the beginning, the primary aim was to save own time and make the process more efficient, however, Boosterberg was developed with the vision of its commercialisation from the beginning. Since the main development was ready and the project was tested by users outside PS:Digital and Kremsa, a long time went by. Moving the product from an alpha version to beta version, which was offered for testing to several other digital agencies, took about 12 months. In this time, mainly usability was tweaked. The product was already used by the two founding agencies in their real projects, however, the user interface was not optimised for using it by a third party. Several rounds of testing the user interface were followed by implementation of the findings and testing it again. In October 2016, the redesigned website was launched and the content was fine-tuned to reflect the current state of the product. In November 2016, a promotion was started to drive traffic to Boosterberg website and get people from all over the world to sign up for the trial. By this time, the major development was finished and the product development was switched to a maintenance mode which also includes further improving usability and some details and implementing new features based on the long-term product roadmap. In the roadmap, requests from Boosterberg users are considered along with the possibilities of the development team and rentability of the implementation.

    Teaming up with Clean Talk

    With the launch of Boosterberg, its support team needed to cover high numbers of requests, both from website users and new Boosterberg clients. Except for the standard contact form, there is an option to chat with Boosterberg representative directly using live chat. Registered users have different kinds of support available in their Boosterberg account as well. Also, the possibility of posting comments by unregistered users on the website requires a lot of support staffs’ attention. To make the time spent with the support as efficient as possible, Boosterberg has decided to implement CleanTalk as an ultimate solution that minimises the amount of spam, both in emails and comments. CleanTalk was recommended by Andrej Miklosik, who is in charge of SEO for Boosterberg and has a positive experience with the CleanTalk WordPress plugin from numerous installations. As he states, “We believe that implementing CleanTalk is the best way to move forward and optimise our time-to-support and experience for our website users.”

  • The difference between nginx and apache with examples

    The difference between nginx and apache with examples

    During interviews for the role, Linux/Unix administrator in many IT companies ask, what is load average, than Nginx is different from apache httpd, and what is a fork. In this article, I will try to explain what expect to hear in response to these questions, and why.

    It is important to understand very well the basics of administration. In an ideal situation, when setting the system administrator tasks put a number of requirements. If the situation is not ideal, it is, in fact, the requirement for the administrator one: “I want to get everything working”. In other words, the service must be available 24/7 and if a decision does not meet these requirements (scalability and fault tolerance are available), we can say that the administrator did the job badly. But if the different solutions of two administrators work 24/7, how to understand which one is better?

    A good system administrator when selecting solution under given requirements focuses on two conditions: minimum consumption of resources and their balanced distribution.

    Option, when for the one expert is needed 10 servers for the job, and for the second expert only 2, we won’t be discussing that here is better – it is obvious. Further, under resources, I understand CPU, RAM and disk drive (HDD).

    Let us consider the situation: one administrator has created a solution which requires 10% CPU, 5% ram and 10% hdd with all your equipment, and the second used 1% CPU, 40% ram, and 20% hdd. Which of these solutions is better? Here everything is not so obvious. Therefore, a good administrator should always be able to competently find a solution on the basis of available resources.

    Imagine that we’re entry-level programmers, and we are asked to write a basic program for working with the network. The requirements are simple: you have to handle two connections simultaneously by protocol TCP and record what we have adopted in a file.

    Before developing an application, you have to remember which tools offered by the Linux operating system (referred to in the article for all the examples only on the basis of this OS). In Linux we have a set of system calls (i.e., functions in the OS kernel, which we can call directly from our program, thereby forcibly giving CPU time to the kernel):

    1. socket — allocates space in the buffer of the OS kernel to fit our socket. The address of the allocated space is returned from the function in the program;
    2. bind — allows to change the information in the structure of the socket, which OS Linux has allocated for us on command socket;
    3. listen – as well as bind changes data in our structure, allowing you to specify the OS that we want to accept connections on this socket;
    4. connect – tells our OS that it needs to connect to another remote socket;
    5. accept – tells our OS that we want to take a new connection from another socket;
    6. read – we ask the OS to give us from its buffer a certain number of bytes, which it received from the remote socket;
    7. write – we ask the OS to send a certain number of bytes to the remote socket.

    In order to establish a connection, we need to create a socket in the Linux memory l, write it in required data and to connect to the remote side.

    socket → bind → connect → read/write

    But if you trust the OS to make the selection of an outbound port for you (as well as the IP address), then bind won’t be necessary:

    socket → connect → read/write

    In order to receive incoming messages, we need to do:

    socket → bind → listen → accept → read/write

    We now know enough to write a program. Proceed directly to writing, using C. Why C? Because of the language of commands with the same name as system calls (with a few exceptions, like a fork).

    The program differ1.c

    
    // The port on which we listen
    
    #define PORT_NO 2222
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <netinet/in.h>
    
    int main(int argc, char *argv[])
    {
    // The buffer where we will read data from a socket
    long buffersize=50;
    int sockfd, newsockfd;
    socklen_t clilen;
    // The variable in which to store the address of our buffer
    char *buffer;
    struct sockaddr_in serv_addr, cli_addr;
    FILE * resultfile;
    // allocated memory
    buffer = malloc (buffersize+1);
    // open the file for writing our messages        
    resultfile = fopen("/tmp/nginx_vs_apache.log","a");
    bzero((char *) &serv_addr, sizeof(serv_addr));
    bzero(buffer,buffersize+1);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(PORT_NO);
    // create a structure (a socket), here SOCK_STREAM it is tcp/ip socket.
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) error("ERROR opening socket");
    // define the structure of the socket, we will listen on port 2222 on all ip addresses
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding");
    // say our OS to accept incoming connections to our socket, maximum 50
    listen(sockfd,50);
    while (1) {
    // in a closed loop process the incoming connection and read from them
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0) error("ERROR on accept");
    read(newsockfd,buffer,buffersize);
    fprintf(resultfile, buffer);
    fflush (resultfile);
    
    }
    close(sockfd);
    return 0;
    
    }
    

    Compile and run our daemon:

    
    [tolik@ localhost]$
    [tolik@localhost]$ ./differ
    

    Look what happened:

    
    [root@ localhost]# ps axuf | grep [d]iffer
    tolik      45409  0.0  0.0   4060   460 pts/12   S+   01:14   0:00  |   \_ ./differ
    [root@localhost ]# netstat -tlnp | grep 2222
    tcp        0      0 0.0.0.0:2222                0.0.0.0:*                   LISTEN      45409/./differ
    [root@localhost ]# ls -lh /proc/45409/fd
    итого 0
    lrwx------ 1 tolik tolik 64 Апр 19 01:16 0 -> /dev/pts/12
    lrwx------ 1 tolik tolik 64 Апр 19 01:16 1 -> /dev/pts/12
    lrwx------ 1 tolik tolik 64 Апр 19 01:16 2 -> /dev/pts/12
    l-wx------ 1 tolik tolik 64 Апр 19 01:16 3 -> /tmp/nginx_vs_apache.log
    lrwx------ 1 tolik tolik 64 Апр 19 01:16 4 -> socket:[42663416]
    [root@localhost ]# netstat -apeen | grep 42663416
    tcp        0      0 0.0.0.0:2222                0.0.0.0:*                   LISTEN      500        42663416   45409/./differ
    [root@localhost ]# strace -p 45409
    Process 45409 attached - interrupt to quit
    accept(4, ^C 
    Process 45409 detached
    [root@localhost ]#
    

    The process is in state sleep (S+ in the ps command).
    This program will continue to execute (get the CPU time) only when a new connection on the port 2222. In all other cases, the program will never get CPU time: it will not even demand it from the OS and therefore will not affect the load avarage (hereafter LA), consuming only a memory.
    On the other console, run the first client:

    
    [tolik@localhost ]$ telnet localhost 2222
    Connected to localhost.
    Escape character is '^]'.
    test client 1
    Look at the file:
    [root@localhost ]# cat /tmp/nginx_vs_apache.log
    test client 1
    Open a second connection:
    [tolik@localhost ]$ telnet localhost 2222
    Connected to localhost.
    Escape character is '^]'.
    test client 2
    

    We see the result:

    
    [root@localhost ]# cat /tmp/nginx_vs_apache.log
    test client 1
    

    The content of the file shows that only the first message has come from the first client. But the second message we have already sent, and it is somewhere. The OS provides all network connections, and then the message test client 2 is now in the buffer of the operating system memory, which is not available to us. The only way to get this data is to process a new connection by command accept, and then call read.

    Let’s try to write something in the first client:

    
    [tolik@localhost ]$ telnet localhost 2222
    Connected to localhost.
    Escape character is '^]'.
    test client 1
    blablabla
    Check the log:
    [root@localhost ]# cat /tmp/nginx_vs_apache.log
    test client 1
    

    New message has not got to the log. This is due to the fact that we call the read command only once, therefore, the log gets only the first message.

    Let’s try to close our first connection:

    
    [tolik@localhost ]$ telnet localhost 2222
    Connected to localhost.
    Escape character is '^]'.
    test client 1
    bla bla bla
    ^]
    telnet> quit
    Connection closed.
    

    At this point, our program runs on the cycle next read and accept, therefore, receives the message from the second connection:

    
    [root@localhost ]# cat /tmp/nginx_vs_apache.log
    test client 1
    test client 2
    

    Our message bla bla bla never appeared, we’d already closed the socket, and the OS has cleared the buffer, thereby removing our data. We need to upgrade the program to read from a socket as long as the information comes out.

    Program with an infinite read from socket differ2.c

    
    #define PORT_NO 2222
    
    #include <stdio.h>
    #include <string.h>
    #include <netinet/in.h>
    int main(int argc, char *argv[])
    {
            int sockfd, newsockfd;
            socklen_t clilen;
            char buffer;
            char * pointbuffer = &buffer;
            struct sockaddr_in serv_addr, cli_addr;
            FILE * resultfile;
            resultfile = fopen("/tmp/nginx_vs_apache.log","a");
            bzero((char *) &serv_addr, sizeof(serv_addr));
            serv_addr.sin_family = AF_INET;
            serv_addr.sin_addr.s_addr = INADDR_ANY;
            serv_addr.sin_port = htons(PORT_NO);
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd < 0) error("ERROR opening socket");
            if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding");
            listen(sockfd,50);
            while (1) {
                    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
                    if (newsockfd < 0) error("ERROR on accept");
                    while (read(newsockfd, pointbuffer,1)) {
                                    fprintf(resultfile, pointbuffer);
                                    fflush (resultfile);
                    }
            }
            close(sockfd);
            return 0;
    }
    

    The program is not much different from the previous one. We added one cycle before the command read to get data from the socket as long as they arrive. Check.

    Clean file:

    
    [root@localhost ]# > /tmp/nginx_vs_apache.log
    Compile and run:
    [tolik@localhost ]$ gcc -o differ differ2.c
    [tolik@localhost ]$ ./differ
    First client:
    [tolik@localhost ]$ telnet localhost 2222
    Connected to localhost.
    Escape character is '^]'.
    client test 1
    yoyoyo
    
    Second client:
    [tolik@localhost ]$ telnet localhost 2222
    Connected to localhost.
    Escape character is '^]'.
    client test 2
    yooyoy
    Check what happened:
    [root@localhost ]# cat /tmp/nginx_vs_apache.log
    client test 1
    yoyoyo
    

    This time all is well, we took all of the data, but the problem remained: two connections are processed sequentially, one by one, and it does not fit our requirements. If we close the first connection (ctrl +]), the data from the second connection will be added directly in the log:

    
    [root@localhost ]# cat /tmp/nginx_vs_apache.log
    client test 1
    yoyoyo
    client test 2
    yooyoy
    

    The data came from. But how to process two connections in parallel? Here we comes to help the command fork. What does the system call fork in linux? The correct answer to this question on any job interview – nothing. Fork – outdated call, and it is presented in linux only for backward compatibility. In fact, calling command fork, you invoke the system call clone. Function clone creates a copy of the process and puts both processes in the queue to CPU. The difference between them is that a fork copies the data (variables, buffers, etc.) directly into the memory space of the child process, while clone copies the data to the child process only if you try to change them (see restrict memory access in the MMU). That is, if you call fork 10 times, and use the data to read-only, you will receive 10 identical copies of data in memory. And this is clearly not what you need, especially in multithread applications. Clone launches a copy of your application, but does not copy the data immediately. If you run clone 10 times, then you will have 10 executable processes with a single block of memory, and the memory will be copied only when you try to change the child process. Agree, the second algorithm is much more effective.
    Program c fork differ3.c

    
    #define PORT_NO 2222
    
    #include 
    #include 
    #include <netinet/in.h>
    
    int main(int argc, char *argv[])
    {
            int sockfd, newsockfd;
            socklen_t clilen;
            char buffer;
            char * pointbuffer = &buffer;
            struct sockaddr_in serv_addr, cli_addr;
            FILE * resultfile;
            int pid=1;
            resultfile = fopen("/tmp/nginx_vs_apache.log","a");
            bzero((char *) &serv_addr, sizeof(serv_addr));
            serv_addr.sin_family = AF_INET;
            serv_addr.sin_addr.s_addr = INADDR_ANY;
            serv_addr.sin_port = htons(PORT_NO);
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd < 0) error("ERROR opening socket");
            if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding");
            listen(sockfd,50);
            while (pid!=0) {
                    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
                    if (newsockfd < 0) error("ERROR on accept");
                    pid=fork();
                    if (pid!=0) {
                            close(newsockfd);
                            fprintf(resultfile,"New process was started with pid=%d\n",pid);
                            fflush (resultfile);
                    }
            }
            while (read(newsockfd, pointbuffer,1)) {
                            fprintf(resultfile, pointbuffer);
                            fflush (resultfile);
            }
            close(sockfd);
            return 0;
    }
    
    

    In this program all the same — we do accept, accept a new connection. Next, we run fork. And if it is the master process (fork returned pid of the created process), then we close the current connection in the parent process (it is available in the parent and in the child process). If it’s a child process (fork returned 0), then we start to read from the open socket that we opened by command accept in the parent process. In fact it turns out that the parent process only accepts connections and read/write we do in child processes.

    Compile and run:

    
    [tolik@localhost ]$ gcc -o differ differ3.c
    [tolik@localhost ]$ ./differ
    

    Clean our log file:

    
    [root@localhost ]# > /tmp/nginx_vs_apache.log
    

    Look processes:

    
    [root@localhost ]# ps axuf | grep [d]iffer
    tolik      45643  0.0  0.0   4060   460 pts/12   S+   01:40   0:00  |   \_ ./differ
    

    Client 1:

    
    [tolik@localhost ]$ telnet localhost 2222
    Connected to localhost.
    Escape character is '^]'.
    client 1 test
    megatest
    

    Client 2:

    
    [tolik@localhost ]$ telnet localhost 2222
    Connected to localhost.
    Escape character is '^]'.
    client2 test
    yoyoyoy
    

    Look processes:

    
    [root@localhost ]# ps axuf | grep [d]iffer
    tolik      45643  0.0  0.0   4060   504 pts/12   S+   01:40   0:00  |   \_ ./differ
    tolik      45663  0.0  0.0   4060   156 pts/12   S+   01:41   0:00  |       \_ ./differ
    tolik      45665  0.0  0.0   4060   160 pts/12   S+   01:41   0:00  |       \_ ./differ
    

    We do not close both connections and can get something else to add, see our log:

    
    [root@localhost ]# cat /tmp/nginx_vs_apache.log
    New process was started with pid=44163
    New process was started with pid=44165
    client 1 test
    megatest
    client2 test
    yoyoyoy
    

    Two connections are processed at the same time – we got the desired result.
    The program works, but not fast enough. It first accepts the connection and then runs the command fork, and the connection only handles one process. The question is: can multiple processes in Linux operating system to work with the same tcp port? Try.

    Program c pre differ_prefork fork.c

    
    #define PORT_NO 2222
    
    #include 
    #include 
    #include <netinet/in.h>
    
    int main(int argc, char *argv[])
    {
            int sockfd, newsockfd, startservers, count ;
            socklen_t clilen;
            char buffer;
            char * pointbuffer = &buffer;
            struct sockaddr_in serv_addr, cli_addr;
            FILE * resultfile;
            int pid=1;
            resultfile = fopen("/tmp/nginx_vs_apache.log","a");
            bzero((char *) &serv_addr, sizeof(serv_addr));
            serv_addr.sin_family = AF_INET;
            serv_addr.sin_addr.s_addr = INADDR_ANY;
            serv_addr.sin_port = htons(PORT_NO);
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd < 0) error("ERROR opening socket");
            if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding");
            listen(sockfd,50);
            startservers=2;
            count = 0;
            while (pid!=0) {
                    if (count < startservers)
                    {
                            pid=fork();
                                    if (pid!=0) {
                                    close(newsockfd);
                                    fprintf(resultfile,"New process was started with pid=%d\n",pid);
                                    fflush (resultfile);
                            }
                    count = count + 1;
                    }
                    //sleep (1);
            }
            newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
            if (newsockfd < 0) error("ERROR on accept");
            while (read(newsockfd, pointbuffer,1)) {
                            fprintf(resultfile, pointbuffer);
                            fflush (resultfile);
            }
            close(sockfd);
            return 0;
    }
    

    As you can see, the program still has not changed much, we just run a fork through the cycle. In this case, we create two child processes, and then each of them does accept to accept a new connection. Check.

    Compile and run:

    
    [tolik@localhost ]$ gcc -o differ differ_prefork.c
    [tolik@localhost ]$ ./differ
    

    Look processes:

    
    [root@localhost ]# ps axuf | grep [d]iffer
    tolik      44194 98.0  0.0   4060   504 pts/12   R+   23:35   0:07  |   \_ ./differ
    tolik      44195  0.0  0.0   4060   152 pts/12   S+   23:35   0:00  |       \_ ./differ
    tolik      44196  0.0  0.0   4060   156 pts/12   S+   23:35   0:00  |       \_ ./differ
    

    We have not joined any of the clients, and the program has already twice made fork. What is happening with the system? For beginning the master process: it is a closed loop and checks whether it is necessary to fork other processes. If we do it without stopping, then, in fact, will constantly require from OS CPU time, as our cycle must always be executed. This means that we consume 100% of one kernel in the command ps value is 98.0%. The same can be seen in the command top:

    
    [root@localhost ]# top -n 1 | head
    top - 23:39:22 up 141 days, 21 min,  8 users,  load average: 1.03, 0.59, 0.23
    Tasks: 195 total,   2 running, 193 sleeping,   0 stopped,   0 zombie
    Cpu(s):  0.3%us,  0.2%sy,  0.0%ni, 99.3%id,  0.2%wa,  0.0%hi,  0.0%si,  0.0%st
    Mem:   1896936k total,  1876280k used,    20656k free,   151208k buffers
    Swap:  4194296k total,   107600k used,  4086696k free,  1003568k cached
    
        PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
      44194 tolik     20   0  4060  504  420 R 98.9  0.0   4:10.54 differ
      44255 root      20   0 15028 1256  884 R  3.8  0.1   0:00.03 top
          1 root      20   0 19232  548  380 S  0.0  0.0   2:17.17 init
    

    If we connect the command strace to the parent, we won’t see anything, because our process does not cause any kernel functions:

    
    [root@localhost ]# strace -p 44194
    Process 44194 attached - interrupt to quit
    ^CProcess 44194 detached
    [root@localhost ]#
    

    What do child processes? Then the fun begins. Judging by the code, all of them after the fork should be hanging in a state of accept and expect new connections from the same port, in our case is 2222. Check:

    
    [root@localhost ]# strace -p 44195
    Process 44195 attached - interrupt to quit
    accept(4, ^C 
    Process 44195 detached
    [root@localhost ]# strace -p 44196
    Process 44196 attached - interrupt to quit
    accept(4, ^C 
    Process 44196 detached
    

    At the moment, they do not require OS CPU time and consume only memory. But here’s the question: who of them will accept my connection, if I do telnet? Check:

    
    [tolik@localhost ]$ telnet localhost 2222
    Connected to localhost.
    Escape character is '^]'.
    client 1 test
    hhh
    [root@localhost ]# strace -p 44459
    Process 44459 attached - interrupt to quit
    read(5, ^C 
    Process 44459 detached
    [root@localhost ]# strace -p 44460
    Process 44460 attached - interrupt to quit
    accept(4, ^C 
    Process 44460 detached
    

    We see that the process that was created earlier (with a lower pid), processed connection of the first, and now is in the read state. If we start a second telnet, the connection will process the following process. After we have finished with the socket, we can close it and go again to the state accept (I do not, in order not to complicate the program).
    Last question remains: what do we do with the parent process so that it does not consume so much cpu and it continued to work? We need to give time to other processes voluntarily, that is “to say” our OS, that for some time we do not need cpu. For this task suitable command sleep 1: if you uncomment it, you will see in strace picture, which repeats once per second:

    
    [root@localhost ]# strace -p 44601
    …..
    rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
    rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    nanosleep({1, 0}, 0x7fff60a15aa0)       = 0
    ….
    rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
    rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    nanosleep({1, 0}, 0x7fff60a15aa0)        = 0
    …
    etc.
    

    Our process will get the CPU about once per second, or at least require it from the OS.
    If you still don’t understand what this long article, then look at the apache httpd running in prefork mode:

    
    [root@www /]# ps axuf | grep [h]ttpd
    root     12730  0.0  0.5 271560 11916 ?        Ss   Feb25   3:14 /usr/sbin/httpd
    apache   19832  0.0  0.3 271692  7200 ?        S    Apr17   0:00  \_ /usr/sbin/httpd
    apache   19833  0.0  0.3 271692  7212 ?        S    Apr17   0:00  \_ /usr/sbin/httpd
    apache   19834  0.0  0.3 271692  7204 ?        S    Apr17   0:00  \_ /usr/sbin/httpd
    apache   19835  0.0  0.3 271692  7200 ?        S    Apr17   0:00  \_ /usr/sbin/httpd
    

    Child processes in accept:

    
    [root@www /]# strace -p 19832
    Process 19832 attached
    accept4(3, ^CProcess 19832 detached
     
    [root@www /]# strace -p 19833
    Process 19833 attached
    accept4(3, ^CProcess 19833 detached
     
    

    The master process with a second pause:

    
    [root@www /]# strace -p 12730
    Process 12730 attached
    select(0, NULL, NULL, NULL, {0, 629715}) = 0 (Timeout)
    wait4(-1, 0x7fff4c9e3fbc, WNOHANG|WSTOPPED, NULL) = 0
    select(0, NULL, NULL, NULL, {1, 0})     = 0 (Timeout)
    wait4(-1, 0x7fff4c9e3fbc, WNOHANG|WSTOPPED, NULL) = 0
    select(0, NULL, NULL, NULL, {1, 0})     = 0 (Timeout)
    wait4(-1, 0x7fff4c9e3fbc, WNOHANG|WSTOPPED, NULL) = 0
    

    When you start the httpd master process spawns child processes, it is easy to see if you run strace on the master process at the time of the launch:

    Run a web server with the following settings:

    
    StartServers       1
    MinSpareServers    9
    MaxSpareServers   10
    ServerLimit       10
    MaxClients        10
    MaxRequestsPerChild  1
    

    These settings say that each child process will handle only a one request, and then process will be killed. The minimum number of processes in accept is 9 and maximum is 10.

    If you run strace on the master process at the start, we see how the master calls the clone until it reaches MinSpareServers.

    Tracing

    
    rt_sigaction(SIGSEGV, {0x7f9991933c20, [], SA_RESTORER|SA_RESETHAND, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGBUS, {0x7f9991933c20, [], SA_RESTORER|SA_RESETHAND, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGABRT, {0x7f9991933c20, [], SA_RESTORER|SA_RESETHAND, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGILL, {0x7f9991933c20, [], SA_RESTORER|SA_RESETHAND, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGFPE, {0x7f9991933c20, [], SA_RESTORER|SA_RESETHAND, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGTERM, {0x7f999193de50, [], SA_RESTORER, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGWINCH, {0x7f999193de50, [], SA_RESTORER, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGINT, {0x7f999193de50, [], SA_RESTORER, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGXCPU, {SIG_DFL, [], SA_RESTORER, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGXFSZ, {SIG_IGN, [], SA_RESTORER, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGPIPE, {SIG_IGN, [], SA_RESTORER, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGHUP, {0x7f999193de80, [HUP USR1], SA_RESTORER, 0x7f99901dd500}, NULL, 8) = 0
    rt_sigaction(SIGUSR1, {0x7f999193de80, [HUP USR1], SA_RESTORER, 0x7f99901dd500}, NULL, 8) = 0
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f99918eeab0) = 13098
    write(2, "[Wed Jan 25 13:24:39 2017] [noti"..., 114) = 114
    wait4(-1, 0x7fffae295fdc, WNOHANG|WSTOPPED, NULL) = 0
    select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f99918eeab0) = 13099
    wait4(-1, 0x7fffae295fdc, WNOHANG|WSTOPPED, NULL) = 0
    select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f99918eeab0) = 13100
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f99918eeab0) = 13101
    wait4(-1, 0x7fffae295fdc, WNOHANG|WSTOPPED, NULL) = 0
    select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f99918eeab0) = 13102
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f99918eeab0) = 13103
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f99918eeab0) = 13104
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f99918eeab0) = 13105
    wait4(-1, 0x7fffae295fdc, WNOHANG|WSTOPPED, NULL) = 0
    select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f99918eeab0) = 13106
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f99918eeab0) = 13107
    wait4(-1, 0x7fffae295fdc, WNOHANG|WSTOPPED, NULL) = 0
    select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
    

    Watch how apache starts – it can easy to look ps axuf | grep [h]ttp every second immediately after the start.

    Start apache

    
    [root@www /]# date; ps axuf | grep [h]ttp
    Wed Jan 25 14:12:10 EST 2017
    root 13342 2.5 0.4 271084 9384? Ss 14:12 0:00 /usr/sbin/httpd
    apache 13344 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    
    [root@www /]# date; ps axuf | grep [h]ttp
    Wed Jan 25 14:12:11 EST 2017
    root 13342 1.6 0.4 271084 9384? Ss 14:12 0:00 /usr/sbin/httpd
    apache 13344 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13348 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    
    [root@www /]# date; ps axuf | grep [h]ttp
    Wed Jan 25 14:12:11 EST 2017
    root 13342 2.0 0.4 271084 9384? Ss 14:12 0:00 /usr/sbin/httpd
    apache 13344 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13348 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13352 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13353 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    
    [root@www /]# date; ps axuf | grep [h]ttp
    Wed Jan 25 14:12:12 EST 2017
    root 13342 1.7 0.4 271084 9384? Ss 14:12 0:00 /usr/sbin/httpd
    apache 13344 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13348 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13352 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13353 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13357 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13358 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13359 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13360 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    
    [root@www /]# date; ps axuf | grep [h]ttp
    Wed Jan 25 14:12:13 EST 2017
    root 13342 1.4 0.4 271084 9384? Ss 14:12 0:00 /usr/sbin/httpd
    apache 13344 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13348 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13352 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13353 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13357 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13358 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13359 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13360 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13364 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    apache 13365 0.0 0.2 271084 5232? S 14:12 0:00 _ /usr/sbin/httpd
    [root@www /]#
    

    So, we have several child processes that are ready to make our http request. Let’s try to send the request:

    
    [root@www /]# wget -O /dev/null http://localhost
    --2017-01-25 14:04:00--  http://localhost/
    Resolving localhost... ::1, 127.0.0.1
    Connecting to localhost|::1|:80... failed: Connection refused.
    Connecting to localhost|127.0.0.1|:80... connected.
    HTTP request sent, awaiting response... 403 Forbidden
    2017-01-25 14:04:00 ERROR 403: Forbidden.
    

    Apache answered us 403, look at the process:

    
    root     13342  0.0  0.4 271084  9384 ?        Ss   14:12   0:00 /usr/sbin/httpd
    apache   13348  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13352  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13353  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13357  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13358  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13359  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13360  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13364  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13365  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    

    As you can see, the process with minimal pid has processed the request and concluded its work:

    
    apache   13344  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    

    Child processes we have got 9 that fits into our limit MinSpareServers.
    Try again to send the request:

    
    [root@www /]# wget -O /dev/null http://localhost
    --2017-01-25 14:15:47--  http://localhost/
    Resolving localhost... ::1, 127.0.0.1
    Connecting to localhost|::1|:80... failed: Connection refused.
    Connecting to localhost|127.0.0.1|:80... connected.
    HTTP request sent, awaiting response... 403 Forbidden
    2017-01-25 14:15:47 ERROR 403: Forbidden.
    [root@www /]# ps axuf | grep [h]ttp
    root     13342  0.0  0.4 271084  9384 ?        Ss   14:12   0:00 /usr/sbin/httpd
    apache   13352  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13353  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13357  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13358  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13359  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13360  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13364  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13365  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13373  0.0  0.2 271084  5232 ?        S    14:15   0:00  \_ /usr/sbin/httpd
    

    This time our request was processed the process

    
    apache   13348  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    

    because now it has minimal pid.
    But we have got 8 free child processes in accept, one is not enough to MinSpareServers, so the master process have created a new process:

    
    apache   13373  0.0  0.2 271084  5232 ?        S    14:15   0:00  \_ /usr/sbin/httpd
    

    Let’s say our OS that it does not give the CPU time to the master process of apache:

    
    [root@www /]# kill -SIGSTOP 13342
    

    The process status has changed, now it doesn’t work.
    Check whether we have a web server is running:

    
    [root@www /]# wget -O /dev/null http://localhost
    --2017-01-25 14:20:12--  http://localhost/
    Resolving localhost... ::1, 127.0.0.1
    Connecting to localhost|::1|:80... failed: Connection refused.
    Connecting to localhost|127.0.0.1|:80... connected.
    HTTP request sent, awaiting response... 403 Forbidden
    2017-01-25 14:20:12 ERROR 403: Forbidden.
    

    Oh yes, still running, the web server is still responding.
    Look what we have with the process:

    
    root     13342  0.0  0.4 271084  9384 ?        Ts   14:12   0:00 /usr/sbin/httpd
    apache   13352  0.0  0.0      0     0 ?        Z    14:12   0:00  \_ [httpd] 
    apache   13353  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13357  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13358  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13359  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13360  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13364  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13365  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13373  0.0  0.2 271084  5232 ?        S    14:15   0:00  \_ /usr/sbin/httpd
    

    Our next request was processed by the next child process, which worked and left. But it left the exit code, which must be processed by the master process. Since the master process is stopped, then the exit code is in the kernel in the process table, and though we don’t have a process there, but in the table it is marked as a zombie.

    
    apache   13352  0.0  0.0      0     0 ?        Z    14:12   0:00  \_ [httpd] 
    

    Naturally the child processes we have 8 new, as the new 9th produce none, master stopped.

    Let’s experiment will send another http request:

    
    [root@www /]# wget -O /dev/null http://localhost
    --2017-01-25 14:25:03--  http://localhost/
    Resolving localhost... ::1, 127.0.0.1
    Connecting to localhost|::1|:80... failed: Connection refused.
    Connecting to localhost|127.0.0.1|:80... connected.
    HTTP request sent, awaiting response... 403 Forbidden
    2017-01-25 14:25:03 ERROR 403: Forbidden.
    [root@www /]# ps axuf | grep [h]ttp
    root     13342  0.0  0.4 271084  9384 ?        Ts   14:12   0:00 /usr/sbin/httpd
    apache   13352  0.0  0.0      0     0 ?        Z    14:12   0:00  \_ [httpd] 
    apache   13353  0.0  0.0      0     0 ?        Z    14:12   0:00  \_ [httpd] 
    apache   13357  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13358  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13359  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13360  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13364  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13365  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13373  0.0  0.2 271084  5232 ?        S    14:15   0:00  \_ /usr/sbin/httpd
    

    Logically, the situation is repeated.

    Let’s say our OS is that the master process can continue to run again:

    
    [root@www /]# kill -SIGCONT 13342
    [root@www /]# ps axuf | grep [h]ttp
    root     13342  0.0  0.4 271084  9384 ?        Ss   14:12   0:00 /usr/sbin/httpd
    apache   13357  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13358  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13359  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13360  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13364  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13365  0.0  0.2 271084  5232 ?        S    14:12   0:00  \_ /usr/sbin/httpd
    apache   13373  0.0  0.2 271084  5232 ?        S    14:15   0:00  \_ /usr/sbin/httpd
    apache   13388  0.0  0.2 271084  5232 ?        S    14:26   0:00  \_ /usr/sbin/httpd
    apache   13389  0.0  0.2 271084  5232 ?        S    14:26   0:00  \_ /usr/sbin/httpd
    apache   13390  0.0  0.2 271084  5232 ?        S    14:26   0:00  \_ /usr/sbin/httpd
    

    The master process immediately read exit code of child processes, and references to them are gone from the process table and the missing processes in the master process to clone again — we now have 10 free processes in accept that fit into the framework of our variables from configs.

    How does nginx? As you know, the system call accept blocks execution of our program as long as no new connection will come. It turns out that we can’t expect a new connection and process already open connection in one process. Or?

    Take a look at the code:

    Code with select

    
    #define PORT 2222
    #include 
    #include    
    #include 
    #include 
    #include    
    #include <arpa/inet.h>    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/time.h>
    
    int main(int argc , char *argv[])
    {
            int opt = 1;
            int master_socket , addrlen , new_socket , client_socket[30] , max_clients = 30 , activity, i , valread , sd;
            int max_sd;
            FILE * resultfile;
            struct sockaddr_in address;
            char buffer[50];
            fd_set readfds;
            resultfile = fopen("/tmp/nginx_vs_apache.log","a");
          // Fill our array of sockets with zeros
            for (i = 0; i < max_clients; i++)  client_socket[i] = 0;
            if( (master_socket = socket(AF_INET , SOCK_STREAM , 0)) == 0)  error("socket failed");
            address.sin_family = AF_INET;
            address.sin_addr.s_addr = INADDR_ANY;
            address.sin_port = htons( PORT );
            if (bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0) error("bind failed");
            if (listen(master_socket, 3) < 0) error("listen");
            addrlen = sizeof(address);
            while(1) //in an endless loop process requests
            {
                FD_ZERO(&readfds);
                FD_SET(master_socket, &readfds);
                max_sd = master_socket;
                for ( i = 0 ; i < max_clients ; i++) { sd = client_socket[i]; if(sd > 0) FD_SET( sd , &readfds);
                    if(sd > max_sd) max_sd = sd;
                }
                // Waiting for events on any of sockets we are interested in
                activity = select( max_sd + 1 , &readfds , NULL , NULL , NULL);
                if ((activity < 0) && (errno!=EINTR))  printf("select error");
                // Processing a new connection
                if (FD_ISSET(master_socket, &readfds))
                {
                    if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) error("accept");
                    for (i = 0; i < max_clients; i++)
                        if( client_socket[i] == 0 ) { client_socket[i] = new_socket; break; }
                }
    
                // Read data from each socket, as we do not know what events caused the OS to give us the CPU
                for (i = 0; i < max_clients; i++)
                {
                    sd = client_socket[i];
                    if (FD_ISSET( sd , &readfds))
                    {
                        if ((valread = read( sd , buffer, 1024)) == 0) { close( sd ); client_socket[i] = 0; }
                        else
                        {
                            buffer[valread] = '\0';
                            fprintf(resultfile, buffer);
                            fflush (resultfile);
                        }
                    }
                }
            }
    
            return 0;
    }
    

    This code looks a bit more complicated than the previous one, but it’s quite easy to explain. For example, in the process need to handle a maximum of 30 connections. We create an array of zeros. As soon as we come to the new connection, we are processing it, and the socket address is recorded in this array. Going through the entire array and all of our sockets, we can consistently read information from them. But how do we know about the new connection without the use of accept? In linux for that there are at least 3 functions: select, poll and epoll. And in freebsd this is the analogue of the function epoll called kqueue (kernel queue). What these commands do? select the oldest feature which is still used in order to give all CPU time to the kernel, requesting it only when certain conditions (like accept). The difference is that the kernel will return cpu to us, when we have specified sockets will start any activity. Because when you start the program open only one socket in select we specify one. If we connect via Telnet to our daemon, in select we need to specify two sockets: the master socket on port 2222 and one that has connected to us. To make it clearer, demonstrate:

    
    [tolik@101host nginx_vs_apache]$ ./differ &
    [1] 44832
    [tolik@101host nginx_vs_apache]$ ps axuf | grep [.]/differ
    tolik     44832 0.0  0.0   4060   448 pts/0    S    22:47   0:00              \_ ./differ
    [root@localhost ]# strace -p 44832
    Process 44832 attached - interrupt to quit
    select(5, [4], NULL, NULL, NULL)        = 1 (in [4])
    

    At this point we make another console telnet on the port 2222 in our daemon and look at the trace:

    
    accept(4, {sa_family=AF_INET, sin_port=htons(41130), sin_addr=inet_addr("127.0.0.1")}, [16]) = 5
    select(6, [4 5], NULL, NULL, NULL^C 
    Process 44832 detached
    [root@localhost ]# ls -lh /proc/44832/fd
    итого 0
    lrwx------ 1 tolik tolik 64 Апр 19 00:26 0 -> /dev/pts/12
    lrwx------ 1 tolik tolik 64 Апр 19 00:26 1 -> /dev/pts/12
    lrwx------ 1 tolik tolik 64 Апр 19 00:21 2 -> /dev/pts/12
    l-wx------ 1 tolik tolik 64 Апр 19 00:26 3 -> /tmp/nginx_vs_apache.log
    lrwx------ 1 tolik tolik 64 Апр 19 00:26 4 -> socket:[42651147]
    lrwx------ 1 tolik tolik 64 Апр 19 00:26 5 -> socket:[42651320] 
    [root@localhost ]# netstat -apeen | grep 42651147
    tcp        0      0 0.0.0.0:2222                0.0.0.0:*                   LISTEN      500        42651147   44832/./differ
    [root@localhost ]# netstat -apeen | grep 42651320
    tcp        0      0 127.0.0.1:2222              127.0.0.1:41130             ESTABLISHED 500        42651320   44832/./differ
    

    First, the command select we have specified the socket 4 (see in brackets). According /proc we learned that the 4th file descriptor is a socket with the number 42651147. According to netstat, we found out that the socket number is our socket in state listen of port 2222. Once we have connected to this socket, the OS made a tcp handshake with our telnet client and installed the new connection, which is notified via the application select. Our program has received the CPU time and began to process an empty array with connections. Seeing that it is a new connection, we run the command accept, knowing that it will not block the program from running, because the connection is already present. In fact, we use the same accept, only in non-blocking mode.

    After we have completed the connection, we again gave control of the linux kernel, but told him that now we want to receive a notice on two sockets, under the number 4 and 5, which is very clearly visible in the command strace ([4 5]). This is how nginx works: it can handle a large number of sockets by one process. According to the existing sockets, we can conduct operations read/write, according to the new can call accept. Select is a very old system call has a number of limitations: for example, the maximum number of connections (file descriptors). It was replaced by a more perfect system call poll, devoid of these limits and working faster. Subsequently appeared epoll and kqueue (in freebsd). More advanced functions allow you to work more effectively with the connection.

    Which of these functions supports nginx? Nginx is able to work with all these features.

    A link to the documentation. In this article I will not describe the differences between all these functions, because the amount of text is already big enough.

    Nginx uses fork to create processes and to load all kernels on the server. But every single child process running nginx with multiple connections in the same way as in the example with select, only uses modern features for this (for linux the default is epoll). Take a look:

    
    [root@localhost ]# ps axuf| grep [n]ginx
    root      232753  0.0  0.0  96592   556 ?        Ss   Feb25   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     232754  0.0  0.0  97428  1400 ?        S    Feb25   5:20  \_ nginx: worker process
    nginx     232755  0.0  0.0  97460  1364 ?        S    Feb25   5:02  \_ nginx: worker process
    [root@localhost ]# strace -p 232754
    Process 232754 attached - interrupt to quit
    epoll_wait(12, ^C 
    Process 232754 detached
    [root@localhost ]# strace -p 232755
    Process 232755 attached - interrupt to quit
    epoll_wait(14, {}, 512, 500)            = 0
    epoll_wait(14, ^C 
    Process 232755 detached
    

    What makes a parent master process nginx?

    
    [root@localhost ]# strace -p 232753
    Process 232753 attached - interrupt to quit
    rt_sigsuspend([]^C 
    Process 232753 detached
    

    It does not accept incoming connections, and only waiting for a signal from the OS. At the signal, nginx is able to a lot of interesting things, for example, to reopen file descriptors, which is useful when log rotation, or to reread the configuration file.

    All interaction between processes nginx carries using unix sockets:

    
    [root@localhost ]# ls -lh /proc/232754/fd
    итого 0
    lrwx------ 1 nginx nginx 64 Апр  8 13:20 0 -> /dev/null
    lrwx------ 1 nginx nginx 64 Апр  8 13:20 1 -> /dev/null
    lrwx------ 1 nginx nginx 64 Апр  8 13:20 10 -> socket:[25069547]
    lrwx------ 1 nginx nginx 64 Апр  8 13:20 11 -> socket:[25069551]
    lrwx------ 1 nginx nginx 64 Апр  8 13:20 12 -> anon_inode:[eventpoll]
    lrwx------ 1 nginx nginx 64 Апр  8 13:20 13 -> anon_inode:[eventfd]
    l-wx------ 1 nginx nginx 64 Апр  8 13:20 2 -> /var/log/nginx/error.log
    lrwx------ 1 nginx nginx 64 Апр  8 13:20 3 -> socket:[25069552]
    l-wx------ 1 nginx nginx 64 Апр  8 13:20 5 -> /var/log/nginx/error.log
    l-wx------ 1 nginx nginx 64 Апр  8 13:20 6 -> /var/log/nginx/access.log
    lrwx------ 1 nginx nginx 64 Апр  8 13:20 9 -> socket:[25069546]
    [root@localhost ]# netstat -apeen | grep 25069547
    tcp        0      0 172.16.0.1:80               0.0.0.0:*                   LISTEN      0          25069547   232753/nginx
    [root@localhost ]# netstat -apeen | grep 25069551
    unix  3      [ ]         STREAM     CONNECTED     25069551 232753/nginx
    

    Result

    Before choosing the tools, it is important to understand exactly how they work. So in some cases it is better to use only apache without httpd nginx – and vice versa. But most often these products are used together, because the parallel processing of sockets in apache is engaged by OS (different processes), and parallel processing of sockets in nginx does nginx itself.

    P.S.
    If after compiling programs do not run, make sure that you do not open the connection on port 2222. In the program I did not handle the situation by closing the sockets, and they can be some time still open in different states from the old demons. If the program does not start, just wait until all sockets are closed by timeout.

    This text is a translation of the article “Разница между nginx и apache с примерами”  published by @mechanicusilius on habrahabr.ru.

    About the CleanTalk service

    CleanTalk is a cloud service to protect websites from spambots. CleanTalk uses protection methods that are invisible to the visitors of the website. This allows you to abandon the methods of protection that require the user to prove that he is a human (captcha, question-answer etc.).

  • About SomeInspiration.com

    Hello, I’m Francis O’Neill, and, among other things, such as looking after the website I’m about to tell you about, I now view myself as a writer. I write on spiritual health and mind, body & spirit topics. I have a couple of books out at this time. In many respects this also encapsulates my business.

    I’ve just hit the big seven-o so I’ve been around the block a few times – or as I like to say, I’ve been around the Sun a few times. I could swear the Earth is speeding up on its journey. It seems I get back to the starting point that bit quicker with each passing year.

    As you may guess by my name, I’m Irish by birth. I have however lived in England for most of my life.

    Road to Damascus

    Let me give you a brief backdrop to my direction of travel. This is germane to what I’m doing on the Web.

    Back in my twenties I wasn’t so spiritually inclined or oriented as I consider myself now. I had by then become secular and existential in my beliefs. I had walked away from a Roman Catholic upbringing. I was in my teens when I began to question my beliefs. Later I went motorcycle racing as something far more preferable to do on Sundays.

    It was from this position, and my developing interest in psychology, that I later came across a book I want to just mention. This was by C.G. Jung; his Memories, Dreams, Reflections. Reading this book literally was a road to Damascus experience for me, a turning point. From that point on I began to look at things differently, exploring life from a different perspective. It helped to give structure to my own thoughts and experiences. And it has since become a lifelong endeavour, that is to gain a clearer understanding of the human situation from a spiritual viewpoint – and to write about it in posts and books.

    My first book, Life and Death: Making Sense of It, is an outcome of my search.  It took some years to research and write. I see the work as a reporting back on what I have discovered on my travels.

    The book could be a challenging perspective for anyone who has yet to think out of the box regarding their existence – or also for the person who has been brought up in a religion that doesn’t incorporate the concept of previous existence and karma. If it interests you, you can easily find out more, and get hold of the book’s Introduction, off lifeanddeaththebook.com.

    Just to finish the bit about me, I have a degree is in Humanistic and Transpersonal Psychology. I’m also a practising astrologer having studied with the Faculty of Astrological Studies and the Mayo School of Astrology in the UK. I’ve spent a good chunk of my life as a field archaeologist, supervising excavations, and also as a qualified lecturer in adult education.

    I live in the Cotswolds (UK) with my partner, Annie Locke. Annie is a musician/composer of essentially classical and romantic melody; that a lot of people also find nostalgic and relaxing to listen to.

    Some Inspiration website

    I began the SomeInspiration.com website back in 2012. This was after being made redundant from a teaching post the year before. Redundancy was a blow but it was also an exciting time of potential. I was given the freedom to begin new adventures.

    From the bat, the site was intended to carry, what I considered, interesting or helpful and inspiring posts, gain visitors and be able to help me to make a living – the latter through affiliate marketing.

    In practice this has entailed promoting my partner’s music plus self-help products. The plan was to also include my book/s at a later stage.

    Although I had been building websites from some time back, using html, for this website I used WordPress. I looked into a number of content management systems and decided upon WP. I love it, and wouldn’t use any other program now. It never ceases to amaze me the work and sophistication that goes into its development – and the amazing array of plugins (such as CleanTalk), which make life so much easier than it was in the early days. To my mind it is one of the better reasons for the Web being in existence.

    Today the website continues to provide the service it more or less began as. But there have been one or two important changes.

    I discovered I was getting a raw deal with the self-hypnosis company I originally had affiliate links with, and so cancelled my relations with them.

    There has also been a change of identity from my earlier use of the site. The site is now more focussed on mind, body & spirit topics than previously was the case.

    Issues in the development of the site

    This mind, body & spirit identity is really a recent development. A website, or blog, having a clear identity, I know now, is key to helping getting traffic, but it took me a while to realise this. When, earlier this year, I decided to create a new website for my first book, I found myself in a bit of a quandary. The Some Inspiration site carried posts that were more appropriate for the book site.

    Rather than replicate them, or cross-link them, I decided to move them across and use redirects. It took a bit of sorting. It was at this juncture that I decided upon the “mind, body & spirit” focus for the site, while the book site was better served carrying articles/posts akin to the content of the book, which is primarily concerned with “spiritual health.” Meanwhile I had also decided to use Some Inspiration as the publisher for my books.

    If mind, body & spirit, and spiritual health sound like the same area of interest, you’re right. They are the same but at different levels, as I perceive them. People interested in mind, body & spirit matters (largely of a self-help nature), are not necessarily interested in, for example, UFOs, ghosts, the paranormal, or the Other Side – as covered in the book.

    Going forward

    I’m now happier with the site and the direction it is going in. There is still a lot more to do to bring it up to speed in the way I envision it. I’m bringing on-board new products. My second book, Steps to Health, Wealth & Inner Peace, is one of those products that is a good fit with the site. I might add that I’m using ClickBank and Amazon for some of my affiliate products.

    All I need now is greater footfall. Well if you are anything like me then getting more traffic is a perennial concern – without which I’m dead in the water, or may as well be. Going forward I’m looking to build more backlinks and to build up my email-list/s as my approach to dealing with this concern. Wish me luck. If you have any tips they are most welcome.

    Well that’s about all I can tell you right now. Stay tuned – and do visit the site. In you write posts, around mind, body & spirit topics, why not consider writing one for Some Inspiration – I won’t bite I promise.

  • Spam Statistics and Trends for a year

    Spam Statistics and Trends for a year

    We have published Anti-Spam Statistics and trends for a year.

    • Statistics include numbers of spam attacks for CMS, Sources of spam by countries.
    • Average spam attacks per day and trends for each CMS.
    • The amount of spam in POST queries.

    https://cleantalk.org/spam-stats

  • Blocking emails by a mask

    Dear users!

    CleanTalk has expanded the functions of personal blacklists. We’ve added an ability to filter email addresses by a mask.

    Symbol asterisk “*” means any set of characters.

    Examples:

    name*@example.com (all e-mail addresses with any set of characters after “name” will be blocked).
    *aa**@ex*****.com (all e-mail addresses with any set of characters before “aa44” will be blocked).
    *kkk*vvv*@example.com (all e-mail addresses with any set of characters before “kkk”, before “vvv” and after “vvv” will be blocked).

    And so on, you can use any combinations of characters and asterisks to make a mask.

    Instructions how to use the personal blacklists can be found here https://cleantalk.org/help/blacklist-usage

  • Blocking spam by nicknames

    Dear users!

    We are pleased to expand opportunities of Stop Words function.

    Added an ability to use stop words to block users whose nicknames contain certain words. This will allow you to use the service to block users with obscene or containing advertising nicknames.

    How to use Stop-Word Feature:

    • Go to your CleanTalk Control Panel.
    • Choose website you want to apply this feature.
    • Press the line “Settings” under the name of your chosen website.
    • Tick the option “Enable comments test via stop list” and press the button “Save“.
    • The line “Stop List” will appear on the right side of the page, click it to add the words you want to be blocked.

    Please note that the changes will be applied in 10-15 minutes.

    The feature is available after purchasing our Extra Package. Go to your Renewal Licence Page to see the details.

  • Reader mode: Pagination in mobile emails

    Development of responsive design make reading emails on mobile devices easier. On the other hand, the side effect is the fact that to read the massive letters now you need a lot of scrolling. As a result, to the end of the message get only the most persistent readers. If you give people the ability to quickly navigate through email, it would greatly improve the situation.

    The described technique works only in the email application Mail for iPhone (Android version in development).

    Reader mode

    The described technique allows the user to independently control the content of the letter –  with a special button letter transforms in version for reading divided into several pages that can be accessed with a click.

    Activation

    A button to enable “reader mode” is wrapped in a label that switches the checkbox with the id of the cell navigation. To display items in this mode, use the pseudo-class :checked, the menu in the top of the panel is set to position:fixed:

    
    <style>
    
    .toolbar-container{
    
    position:fixed;
    
    top:0px; left:0px;
    
    display:none;
    
    ...
    
    }
    
     
    
    #navbox:checked ~ .toolbar-container{
    
    display:block!important;
    
    }
    
     
    
    #navbox:checked ~ .articles-container{
    
    height:100%;
    
    overflow:hidden;
    
    position:fixed;
    
    top:50px;
    
    left:0px;
    
    }
    
    </style>
    
    
     
    
    <input id="navbox" type="checkbox">
    
    <label for="navbox" >Activate Reader Mode</label>
    
     
    
    <div class="toolbar-container">...hidden toolbar content ... <div>
    
    <div class="articles-container">
    
    article1, article2, article3...
    
    </div>
    

    Pagination of articles

    Article wrapped in two containers. When activated the selector :checked, outer container displays the content on the full width and height of the visible area of the screen. The outer container is also set at a fixed value at the top of email messages minus the space occupied by the menu.

    The inner container occupies the width of the visible area multiplied by the number of articles. Articles also occupy a width in the viewport and shifted to the left. This allows you to organize them in a horizontal position, displaying one article at a time.

    Then you create a radio-element for each article, when the selector :checked is set in a certain radio-element, the inner container is shifted left or right by the number of “width crane” (vw) of each article. Adding a transition allows for the “sliding effect” while browsing articles:

    
    #navbox:checked ~ #a1radio:checked ~ .articles-cont .articles{  left:0px;}#navbox:checked ~ #a2radio:checked ~ .articles-cont .articles{  left:-100vw;}#navbox:checked ~ #a3radio:checked ~ .articles-cont .articles{  left:-200vw;}
    

    The value of vw does not work on Android, so you’ll have to arrange the articles one above the other and show the right, hiding or changing its z-index.

    Moving on articles

    To navigate through the articles, create labels of arrows, which will be activated by clicking the appropriate radio-element. These labels are hidden by default and displayed only a couple associated with the currently visible article.

    
    <style>#navbox:checked ~ #a1radio:checked ~ .toolbar-cont .a1nav,#navbox:checked ~ #a2radio:checked ~ .toolbar-cont .a2nav,#navbox:checked ~ #a3radio:checked ~ .toolbar-cont .a3nav{  display:block;}</style> <div class="nav-arrows a1nav">   <label> </label><label for="a2radio">»</label></div><div class="nav-arrows a2nav">   <label for="a1radio">«</label><label for="a3radio">»</label></div><div class="nav-arrows a3nav">   <label for="a2radio">«</label><label> </label></div>

    Index menu of articles

    Index menu contains a list of labels associated with articles in a hidden and absolutely positioned div, and is displayed when the user clicks on a menu, use the selector :hover.

    Interesting point, often if the menu is hidden right after selecting the element, the mail client just ignores the selection. To cope with this problem you can add the transition and delay.

    Code

    To work with the code of the example you can in the builder of one of the email services. In text form it is presented under the spoiler:

    The code of the example

    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta name="viewport" content="width=device-width" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <style>
    * {
    margin:0;
    padding:0;
    font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
    font-size: 100%;
    line-height: 1.5;
    color:#333333;
    }
    img{
    max-width:100%;
    }
    body {
    -webkit-text-size-adjust:none;
    width: 100%!important;
    height: 100%;
    }
    h1,h2{
    margin-bottom:15px;
    line-height: 1.3;
    font-weight:300;
    }
    h1 {
    font-size: 32px;
    }
    h2 {
    font-size: 22px;
    }
    .toolbar-cont{
    max-height:none!important;
    overflow:visible!important;
    z-index:10;
    width:100%;
    position:fixed;
    top:0px;
    left:0px;
    display:none;
    height:50px;
    background-color:#eeeeee;
    border-bottom:1px solid #222222;
    }
    .toolbar{
    height:50px;
    line-height:50px;
    display:block;
    text-decoration:none;
    }
    .toolbar-menu{
    z-index:10;
    text-align:center;
    position:absolute;
    top:51px;
    overflow:hidden;
    transition: all 0.3s;
    -webkit-transition: all 0.3s;
    transform: rotateX(90deg);
    -webkit-transform: rotateX(90deg);
    transform-origin: top;
    -webkit-transform-origin: top;
    -webkit-transition-delay: 0.5s;
    transition-delay: 0.5s;
    }
    .toolbar-menu label{
    display:block;
    padding:5px 20px 5px 20px;
    }
    .toolbar:hover + .toolbar-menu{
    display:block;
    transform: rotateX(0deg);
    -webkit-transform: rotateX(0deg);
    }
    .articles-cont{
    background-color:#ffffff;
    }
    
    #navbox:checked ~ .articles-cont{
    width:100%;
    height:100%;
    overflow:hidden;
    position:fixed;
    top:50px;
    left:0px;
    }
    #navbox:checked ~ .articles-cont .articles{
    position:absolute;
    left:0px;
    width:303vw;
    transition: all 0.3s;
    -webkit-transition: all 0.3s;
    height:100%;
    }
    #navbox:checked ~ .articles-cont .articles .art{
    width:100vw;
    float:left;
    height:1000px;
    overflow:hidden;
    }
    #navbox:checked ~ .articles-cont .articles .art div{
    width:90vw;
    padding:20px 5vw 10px 5vw;
    }
    input{
    max-height:0;
    display:none;
    }
    .nav-arrows{
    float:right;
    display:none;
    }
    .nav-arrows label{
    cursor:pointer;
    display:inline-block;
    vertical-align:middle;
    text-align:center;
    height:50px;
    width:50px;
    font-size:30px;
    font-weight:bold;
    }
    #navbox:checked ~ #a1radio:checked ~ .articles-cont .articles{
    left:0px;
    }
    #navbox:checked ~ #a2radio:checked ~ .articles-cont .articles{
    left:-100vw;
    }
    #navbox:checked ~ #a3radio:checked ~ .articles-cont .articles{
    left:-200vw;
    }
    #navbox:checked ~ #a1radio:checked ~ .articles-cont .a1,
    #navbox:checked ~ #a2radio:checked ~ .articles-cont .a2,
    #navbox:checked ~ #a3radio:checked ~ .articles-cont .a3{
    height:100%;
    overflow-y:scroll;
    }
    #navbox:checked ~ #a1radio:checked ~ .toolbar-cont .a1nav,
    #navbox:checked ~ #a2radio:checked ~ .toolbar-cont .a2nav,
    #navbox:checked ~ #a3radio:checked ~ .toolbar-cont .a3nav{
    display:block;
    }
    .closer{
    display:inline-block;
    vertical-align:middle;
    text-align:center;
    height:50px;
    width:50px;
    font-size:30px;
    font-weight:bold;
    float:left;
    }
    #navbox:checked ~ .opener{
    display:none;
    }
    #navbox:checked ~ .toolbar-cont{
    display:block!important;
    }
    
    @media screen and (max-width: 480px) {
    #cbox-capable:checked ~ .opener div{
    margin:10px auto;
    background-color:#1abc9c;
    color:#ffffff;
    border-radius:5px;
    display: block !important;
    max-height:50px !important;
    line-height:50px;
    text-align:center;
    vertical-align:middle;
    }
    }
    </style>
    </head>
    <body>
    <div id="main-cont" style="padding:20px;">
    <h1>FreshInbox</h1>
    <div style="dislay:block;width:350px;margin:0px auto;max-width:100%">
    <img src="http://placehold.it/350x150">
    </div>
    <!--[if !mso 9]><!-->
    <input id="cbox-capable" type="checkbox" style="display:none!important;max-height:0;visibility:hidden;" checked>
    <input id="navbox" type="checkbox" style="display:none!important;max-height:0;visibility:hidden;">
    <label for="navbox" class="opener">
    <div style="display:none;max-height:0px;overflow:hidden;cursor:pointer">Reader Mode</div></label>
    <input id="a1radio" name="qradio" type="radio" checked style="display:none!important;max-height:0;visibility:hidden;">
    <input id="a2radio" name="qradio" type="radio" style="display:none!important;max-height:0;visibility:hidden;">
    <input id="a3radio" name="qradio" type="radio" style="display:none!important;max-height:0;visibility:hidden;">
    
    <div class="toolbar-cont" style="display:none;max-height:0px;overflow:hidden;">
    <label for="navbox" class="closer">x</label>
    <div class="nav-arrows a1nav">
    <label> </label><label for="a2radio">»</label>
    </div>
    <div class="nav-arrows a2nav">
    <label for="a1radio">«</label><label for="a3radio">»</label>
    </div>
    <div class="nav-arrows a3nav">
    <label for="a2radio">«</label><label> </label>
    </div>
    
    <a href="#" class="toolbar">Article Index...</a>
    <div class="toolbar-menu" style="text-align:left;background-color:#C8DEFA;border:1px solid #888888;font-size:15px;">
    <label for="a1radio">Yahoo! Mail Fixes Media Query Bug. Yahoo!!!</label>
    <label for="a2radio">Outlook.com and Background Images</label>
    <label for="a3radio">Gmail iOS Increases Email Font Sizes – Again</label>
    </div>
    </div>
    <!--<![endif]-->
    
    <div class="articles-cont">
    <div class="articles">
    <div class="art a1"><div>
    <h2>Yahoo! Mail Fixes Media Query Bug. Yahoo!!!</h2>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    <HR>
    
    </div></div>
    <div class="art a2"><div>
    <h2>Outlook.com and Background Images</h2>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    <HR>
    
    </div></div>
    <div class="art a3"><div>
    <h2>Gmail iOS Increases Email Font Sizes – Again</h2>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    <HR>
    
    </div></div>
    </div>
    </div>
    </div>
    </body>
    </html>
    <b>
    

    This text is a translation of the article “Режим читателя: Пагинация в мобильных email-письмах”  published by @lol_wat on habrahabr.ru.

    About the CleanTalk service

    CleanTalk is a cloud service to protect websites from spam bots. CleanTalk uses protection methods that are invisible to the visitors of the website. This allows you to abandon the methods of protection that require the user to prove that he is a human (captcha, question-answer etc.).

  • WordCamp Europe in Vienna and the vector of development of WordPress

    WordCamp Europe in Vienna and the vector of development of WordPress

    This year the conference WordCamp Europe 2016 took place in Vienna and attracted more than 2300 guests. The capital of Austria is an excellent choice for such events, there are all conditions: convenient location, large meeting halls, and an active WordPress community. And there is something to see after the conference. Several of our developers have been on WordCamp Europe 2016. Under the cut – their story about the most interesting presentations and events.

    The format of the conference

    The conference lasted three days: the first two days we listened to the speeches, and the last day was given to the contributors. The reports were in different categories: Development, Design, Business, Content, Community, and took place in three streams, so everyone can find something interesting for yourself. Much attention speakers paid to high load questions, Continuous Integration, REST APIs, and the project Calypso.

    On the day of contributors signed up about 600 volunteers. On this day it was possible to take a direct part in the development of WordPress, to learn how to work the kernel developers, translators, as well as the team checking the plugins and themes to the official catalog. You can even get advice on the organization of WordPress community in your city.

    A nice bonus was the performance of Matt Mullenweg, the developer and the founder of WordPress, the founder of Automattic, WordPress.com, Akismet. But more on that below.

    The most interesting report

    PHP7 and WordPress

    The release of PHP7 could not remain unnoticed at WordCamp Europe: how to provide the work of WordPress on PHP7, said Dan Blows in his report What’s New in PHP7 and what to expect in PHP7.1.

    The core of WordPress and many plugins already support PHP7. Quoting the author, we can say: “Upgrade to PHP 7 easily, and probably everything will work immediately”. But he raised the points that should pay attention if you decided to migrate your website to PHP7.

    The speaker told about innovations in PHP and the benefits that you can get when going to the seventh version. Dan showed impressive statistics of speed up of work WordPress on PHP7 compared to PHP 5.6.

    A couple of reports about WordPress REST API

    Especially important were the reports about REST API. This is one of the most important and actively developing directions. News from the developers WordPress rest API, about the difficulties and decisions is incredibly valuable information. Thanks Joe Hoyle and Adam White! Look at their performances The Ultimate REST API talk and Using the REST API and JavaScript to create better WordPress interfaces.

    The reports disclosed the questions associated with use of the API and its development and expansion.

    Now REST API is not yet part of the core, it exists in the form of a plugin. Adam in his report underlines the benefits that will get WordPress with integration of REST in its core. However, we now have the opportunity to build our apps using the new API.

    The REST API gives unprecedented flexibility and expression “WordPress is limited only by your imagination” becomes a reality.

    Dashboard Calypso

    Due attention has been given to the relatively new development — Calypso. This is the administration panel of WordPress-sites, written in JS and running using WordPress REST API, which will definitely become popular.

    Designer Calypso told about the project in general, and about what it cost for the team this his development and shared approaches in organization effective communication in the project. As Davide Casali said: “Communication is the oxygen”. It is impossible not to agree.

    Experience of building a highly loaded WP-site

    WordPress has long been used for the development of high-load news portals. Such giants as TED, TechCrunch, CNN, NBC built their sites on it. Yes, to build a high-load website is not easy, but speakers from NewsCorp Australia told how to do everything correctly.

    Their experience – another precedent, proving the possibility of building on WP portals with millions of page views per day. Speakers gave valuable information about the development team and working process, talked about continuous integration, environment and visitor statistics. They also shared information that will help you to calculate the necessary costs for such a project.

    Incredibly useful report, including from the point of view of communication with clients: How NewsCorp Australia scaled WordPress to host Australias largest ‘news’ websites on WordPress VIP.

    About legacy-projects

    Andrew Nacin — Lead-developer of WordPress core. With years of experience in the development of such a popular CMS system, the kernel developers have identified and summarized the key points of the philosophy of WordPress, which adheres and Andrew.

    Get the big project “inherited” from people who have not really thought about the future is always difficult. And even painful. If you have such a project, the Andrew report will help to understand how to transform it in a stable and not require inappropriate investment product. Video of the report is available at the link.

    Elasticsearch and ElasticPress

    Full text search for MySQL databases by itself is not the best solution. But on high load sites and sites with large volumes of data — even more so. Elasticsearch is one of the solutions to implement an efficient search. How it works, how to configure Elasticsearch, how to protect data, and finally how to use it in your projects? These questions are answered by Taylor Lovett in the report Modernizing WordPress Search with Elasticsearch.

    Taylor also tells about the plugin ElasticPress. The speaker is one of the developers of this plugin and knows what he’s talking about. In general, meetings with the developers of the components is always a unique opportunity to get information about the details of the use and future development plans.

    The report about security

    Of course, the most popular platform for developing websites in the world is one of the most attacked. So you need to constantly pay attention to the issue of information security.

    Maurizio Pelizzone gave a presentation about securing WordPress websites: WordPress Hardening – Ten tips in ten minutes. The lecturer gave useful tips on how to reduce the risk to be hacked and sleep well.

    Copywriting for professionals

    At the end of the first day of the conference was the author of the best SEO-plugin for WordPress Joost de Valk and his wife Marieke van de Rakt. The report Beyond SEO – Copywriting for professionals, they told about the next stage in the evolution of search engines and the importance of high-quality texts.

    Speakers against the “scorched earth tactics”. Joost and Marieke prefer sustainable and holistic approach to SEO, which involves focusing on all areas of optimization:

    • The technical quality.
    • Good UX & UI.
    • Impeccable security.
    • Great PR & Social

    The basis of this approach is the high-quality content. And the principles of such content were presented in the report. In addition, the speakers spoke about a new functionality of their plugin, which allows you to make recommendations for improvement of the texts on your website.

    Interview with Matt Mullenweg

    Special attention deserves an interview with Matt Mullenweg: Interview and Q&A. the speech of Matt is a traditional part of WordCamp Europe. Right on the stage there is a sofa and provided almost homely atmosphere. In the second part of the perfomance, Matt talked to the audience.

    They discussed potentially leading role REST API and interfaces on  JS. Talked about the most successful and promising projects: Jetpack, WooCommerce and WordPress.com that do a lot for the success of WordPress in particular, and for an open Internet in general. Remembered about competitors, but Matt doesn’t consider them dangerous.

    And much more

    There were other interesting presentations, which we did not visit because we could not be simultaneously on all three streams. A complete list of video, as always, loaded on wordpress.tv.

    Day contributors, how to develop core of WP

    The conference was not limited by two days, full of interesting presentations and communication. For special interested was scheduled Contributor Day, which signed up about 600 people. It was held at the University of Vienna, Faculty of Informatics.

    Each of the participants chose the direction in which he can get acquainted with the process of open-source development and to assist in the development of WordPress. Among the areas were: the development of the core, development of plugins and themes, internationalization, design, marketing, and support. Each group was coordinated by an experienced supervisor. The motto for the day was “Thank WordPress”. You could join the community, gain new experience, improve your professional level and make WordPress better.

    The future of WordPress

    WordPress is actively developed. The most interesting and promising areas — REST API and JavaScript interfaces. And the last were possible thanks to partly all the same REST API.

    A lot of improvements in the core, for example, in recent releases significantly improved internationalization. Technology stack, development approaches, tools, and more — all have changed greatly since the advent of the first version of WordPress. There is movement forward, we are seeing regular releases that add something new.

    Good news is that the core already supports PHP7. We already develop projects at NIX Solutions on a fresh PHP. But as for a full transition to the seventh version, here the prospect is not very encouraging. The fact that plugins and themes are supported by the community and by individual companies and not all of them in a hurry to implement support for PHP7.

    What’s more surprising at the conference in Vienna is the maturity of the European community and a serious attitude to WP. We are sure that with such a large, active and talented community, WordPress has a great future.

    Next WCEU 2017 in Paris

    At the end of the conference, according to tradition, was announced the next city for WordCamp Europe, it became the capital of France. See you in Paris!

    This text is a translation of the article “WordCamp Europe в Вене и вектор развития WordPress”  published by @NIX_Solutions on habrahabr.ru.

    About the CleanTalk service

    CleanTalk is a cloud service to protect websites from spam bots. CleanTalk uses protection methods that are invisible to the visitors of the website. This allows you to abandon the methods of protection that require the user to prove that he is a human (captcha, question-answer etc.).