Based on a custom protocol server of high concurrent processing: multi-threaded model

https://www.cnblogs.com/lan0725/p/11634267.html  simply processing, the server returned to the client a time, and then close the socket.

If you want two-way communication, the server is bound to call the read function, but read the default blocked, if the client does not send data to the server, the main thread has been blocked, other clients can not connect successfully. This requires handling high concurrency issues.

Three ways to deal with the high concurrent server

  1. Multi-process  https://www.cnblogs.com/lan0725/p/11634709.html
  2. Multithreading  https://www.cnblogs.com/lan0725/p/11639142.html
  3.  I / O multiplexer

 Makefile directory of settings are described in which multiple processes  https://www.cnblogs.com/lan0725/p/11634709.html

Significantly higher than the efficiency of multi-threaded multi-process, but also because most of the threads share the process space, and multi-process copy space, thereby reducing system overhead.

  1. The main thread is only responsible accepte, and then create a child thread with a separate property.
  2. Each client is connected to maintain a thread with a separate property, to do two-way communication in this thread. That is how many client connections, the number of child thread will open up.

With the same client and multi-process.

There are actually only when the main function accept difference, to create a separate thread, eliminating the need to wait for the main thread to join the recovery thread. Specific do_something no difference.

Multi-threaded server 2_echo_multhread_tcp_server.c:

#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "msg.h"
#include <errno.h>
#include <pthread.h>

#define SERVER_PORT 8888
#define LISTEN_QUEUE_SISE 10

int socketfd;

void signal_handler(int signo)
{
    if (signo == SIGINT)
    {
        printf("this serveice close\n");
        close(socketfd);
        exit(1);
    }
}

void print_clientinfo(int fd, const char* type)
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t len = sizeof(addr);

    if(getpeername(fd, (structthe sockaddr *) & addr, & len) < 0 ) 
    { 
        perror ( " the getpeername error " );
         return ; 
    } 

    char ipstr [ 16 ]; 
    Memset (ipstr, 0 , the sizeof (ipstr));
     // the address from the network byte order conversion dotted decimal 
    inet_ntop (AF_INET, & addr.sin_addr.s_addr, ipstr, the sizeof (ipstr)); 

    the printf ( " % S (% D)% S \ n- " , ipstr, ntohs (addr.sin_port), type); 
} 

void do_something ( int FD) 
{ 
    char BUFF [1024 ];
     the while ( . 1 ) 
    { 
        // read the contents sent by the client 
        Memset (BUFF, 0 , the sizeof (BUFF)); 
        size_t size = read_msg (FD, BUFF, the sizeof (BUFF));
         IF (size < 0 ) 
        { 
            // protocol error while out of the back end of the main sub-process 
            perror ( " read_msg error " );
             BREAK ; 
        } 
        the else  IF (size == 0 ) 
        { 
            / *  client disconnected hung up out of the while will end child thread
             * * /
            BREAK ; 
        } 
        
        the printf ( " recev from Client:% S \ n- " , BUFF); 

        // write data back to 
        IF (write_msg (FD, BUFF, the sizeof (BUFF)) < 0 ) 
        { 
            IF (errno == EPIPE) 
            { 
                / * the client disconnects   
                 * signal generating SIGPIPE 
                 * is set to the error EPIPE 
                 * this determination can therefore also be captured errno SIGPIPE signal 
                 * commonly known as pipeline burst 
                 * out while the child thread will end 
                 * * / 
                BREAK ; 
            } 
            

            perror ( "write_msg error");
        }
    }
}

void* threadWork(void* arg)
{
    int fd = (int)arg;
    print_clientinfo(fd, "connected");
    do_something(fd);
    print_clientinfo(fd, "closed");
    close(fd);
    return NULL;
}


int main(int argc, char const *argv[])
{
    if(Signal (SIGINT, signal_handler) == SIG_ERR)
    { 
        Perror ( " Signal error " ); 
        Exit ( . 1 ); 
    } 

    // . 1 sokect
     // AF_INET IPv4
     // SOCK_STREAM TCP 
    IF ((socketfd = Socket (AF_INET, SOCK_STREAM, 0 )) < 0 ) 
    { 
        perror ( " Socket error " ); 
        Exit ( . 1 ); 
    } 

    // 2 binding the bind local address and port 
    struct the sockaddr_in ServerAddr; 
    Memset ( & ServerAddr, 0 , the sizeof(ServerAddr)); 
    serveraddr.sin_family = AF_INET; // IPv4 
    serveraddr.sin_port = the htons (SERVER_PORT); // port 
    serveraddr.sin_addr.s_addr = htonl (INADDR_ANY); // response to a request of any card 
    IF (the bind (socketfd, ( struct the sockaddr *) & ServerAddr, the sizeof (ServerAddr)) < 0 ) 
    { 
        perror ( " the bind error " ); 
        Exit ( . 1 ); 
    } 

    // . 3 the listen start listening notification system accepts from the client connections ready connection queue 
    IF (the listen (socketfd, LISTEN_QUEUE_SISE) < 0 ) 
    { 
        Perror ( " the listen error " ); 
        Exit ( . 1 ); 
    } 

    pthread_t Thread; 
    // set the separation property does not need the main thread calls the relevant sub-thread pthread_join recovering 
    the pthread_attr_t is attr; 
    pthread_attr_init ( & attr); 
    pthread_attr_setdetachstate ( & attr, PTHREAD_CREATE_DETACHED);
     int retno;
     the while ( . 1 ) 
    {     
        // . 4 Accept out from the first queue 
        int clientfd = Accept (socketfd, NULL, NULL);
         IF (clientfd < 0 ) 
        {
            perror (" Accept error " );
             Continue ; 
        } 
        // . 5 creating the separate attribute child thread made read / write in the sub-thread 
        IF ((retno = pthread_create (& Thread, & attr, 
            threadWork, ( void *) clientfd)) =! 0 ) 
        { 
            the printf ( " error nuber:% D,% S \ n- " , retno, the strerror (retno)); 
            Close (clientfd); 
            Continue ; 
        } 

    } 
    
    // destroy threads property 
    pthread_attr_destroy (& attr);
     // . 6 Close 
    Close (socketfd);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/lan0725/p/11639142.html