The Linux thread pool is simple to apply on the server

Source: Internet
Author: User
Tags mutex set socket htons

I. Descriptive narrative of the problem

Now take the C/s architecture as an example. The client sends a number to the server to find, and the server side initiates the thread in the thread to make the corresponding query. Displays the results of the query.

Second, the implementation of the programme

1. The entire project is organized by client, server, and Lib. For example, as seen in:

watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvd2fuz3poawnozw5nmtk4mw==/font/5a6l5l2t/fontsize/400/fill/ I0jbqkfcma==/dissolve/70/gravity/center ">

2. Enter Lib.


Socket.h, socket.c

/** @filesocket. h @briefSocket API header file TCP Socket utility functions, it provides s  Imple functions that helps to build TCP client/server. @author Wangzhicheng */#ifndef socket_h#define socket_h#include <stdio.h> #include <stdlib.h> #include < string.h> #include <errno.h> #include <sys/socket.h> #include <sys/types.h> #include <resolv.h > #include <fcntl.h> #define MAX_CONNECTION20INTTCPSERVERINIT (int port, int *serverfd); inttcpserverwaitconnection (int serverfd, int *clientfd, char *clientaddr); int Tcpserverselect (int* serverfdlist, int num, int *clientfd, char *clientaddr), inttcpclientinit (int *clientfd); inttcpclientconnect (const int CLIENTFD, const char *addr, int port); inttcpnonblockread (int clientfd, char* buf, int size); int tcpblockread (int clientfd, char* buf, int size); inttcpwrite (int clientfd, char* buf, int size), void tcpclientclose (int sockfd), void tcpserverclose (int sockfd); endif 


Socket.c

#include "socket.h"/* * @briefinitialize TCP Server * @portport number for socket * @serverfdserver Socket FD * return ser Ver socked FD for success, on error return error code * */INTTCPSERVERINIT (int port, int *serverfd) {struct sockaddr_in de st;//create socket, same as CLIENT*SERVERFD = socket (pf_inet, sock_stream, ipproto_tcp); if (*serverfd < 0) return-1;/ Initialize Structure Destmemset ((void*) &dest, ' ', sizeof (dest));d est.sin_family = Pf_inet;dest.sin_port = Htons (port);d est.sin_addr.s_addr = inaddr_any;//Assign A port number to Socketbind (*SERVERFD, (struct sockaddr*) &de St, sizeof (dest)); return *SERVERFD;} /* * @briefwait client connect * @serverfdserver Socket FD * @clientfdclient Socket FD * @clientaddrclient address which C Onnect to Server * Return client FD, on Error return error code * */inttcpserverwaitconnection (int serverfd, int *clientfd , char *clientaddr) {struct sockaddr_in client_addr;socklen_t addrlen = sizeof (CLIENT_ADDR);//Make it listen to SockeTlisten (SERVERFD);//Wait and accept connection*clientfd = Accept (SERVERFD, (struct sockaddr*) &client_addr, &amp ; addrlen); strcpy (clientaddr, (const char *) (Inet_ntoa (CLIENT_ADDR.SIN_ADDR))); return *clientfd;} /* * @briefinitialize TCP client * @clientfdclient Socket FD * Return client socked FD for success, on error return error Code */inttcpclientinit (int *clientfd) {*CLIENTFD = socket (pf_inet, sock_stream, 0); return *clientfd;} /* * @briefconnect to TCP server * @clientfdclient Socket FD * @addrserver address * @portserver Port number * Return 0 fo R success, on Error-1 is returned */inttcpclientconnect (const int CLIENTFD, const char *addr, int port) {struct SOCKADDR_ In dest;//Initialize value in Destmemset (&dest, '% ', sizeof (dest));d est.sin_family = Pf_inet;dest.sin_port = Htons ( Port); Inet_aton (addr, &dest.sin_addr);//Connecting to Serverreturn Connect (clientfd, (struct sockaddr*) &dest , sizeof (dest));} /* * @briefnon-block read from TCP socket * @clientfdsockET FD * @buf input buffer * @sizebuffer size * Return the length of read data */inttcpnonblockread (int clientfd, CH ar* buf, int size) {int opts;opts = Fcntl (CLIENTFD, F_GETFL); opts = (opts | O_nonblock); Fcntl (Clientfd, F_SETFL, opts); return recv (CLIENTFD, buf, size, 0);}  /* * @briefblock read from TCP socket * @clientfdsocket FD * @buf Input buffer * @sizebuf size * Return the length of read data */inttcpblockread (int clientfd, char* buf, int size) {int opts;opts = Fcntl (CLIENTFD, F_GETFL); opts = (opts & ~o_nonblock); Fcntl (Clientfd, F_SETFL, opts); return recv (CLIENTFD, buf, size, 0);} /* * @briefwrite to TCP socket * @clientfdsocket FD * @buf output BUF * @sizeoutput buf length * Return the length O f the actual written data, -1:disconnected */inttcpwrite (int clientfd, char* buf, int size) {int len= 0;/* set socket to Nonblock */int ret = fcntl (CLIENTFD, F_GETFL), ret |= o_nonblock;if (fcntl (CLIENTFD, F_SETFL, ret) < 0) {printf ("set so Cket to Nonblock fail [%d]!\n ", errno);} Len = Send (CLIENTFD, buf, size, msg_nosignal); return Len;}  /* * @briefclose the TCP connection * @sockfdsocket FD * returnnone */void tcpconnectionclose (int sockfd) {close (SOCKFD);}


Threadpool.h

#ifndef threadpool_h#define threadpool_h#include <stdio.h> #include <stdlib.h> #include <pthread.h>    #include <unistd.h>struct job{void* (*callback_function) (void *arg);                                Thread callback function void *arg; callback function parameter struct job *next;};                   struct threadpool{int thread_num;                Number of threads opened in the thread pool int queue_max_num;                 The number of maximum jobs in the queue struct job *head;                 The head pointer to the job *tail the struct job;              The tail pointer pointing to the job pthread_t *pthreads;            pthread_t pthread_mutex_t Mutex for all threads in the thread pool;       Mutual rejection signal volume pthread_cond_t queue_empty;   The condition variable of the queue is empty pthread_cond_t queue_not_empty;    Queue is not empty condition variable pthread_cond_t queue_not_full;                The queue is not full of condition variables int queue_cur_num;                  Queue current job number int queue_close;                   Whether the queue has closed int pool_close; Whether the thread pool has been closed};//================================================================================================//function Name: threadpool_init//function Description Description: Initialize thread pool//input: [in] thread_num thread pool Open Number of threads//[in] queue_max_num queue maximum jobs//output: none//return: Success: thread pool ground Address failed: null//================================================================================================ struct threadpool* threadpool_init (int thread_num, int queue_max_num);//===========================================                  =====================================================//function Name: threadpool_add_job//function Descriptive narrative:     Join a task to the thread pool//input: [in] pool thread pool address//[in] callback_function                     callback function//[in] ARG callback function//output: none//return: Success: 0 Failure: -1//================================================================================================int Threadpool_add_job (struct ThreadPool *pool, void* (*callback_function) (void *arg), void *arg);//=========================================================================                      =======================//function Name: threadpool_destroy//function Description: Destroy thread pool//input: [in] pool thread pool address//output: none//return: Success: 0 Failure: -1//================== ==============================================================================int Threadpool_destroy (struct ThreadPool *pool);//===========================================================================================                  =====//function Name: threadpool_function//function Description Description: Thread pool threads function//input: [in] Arg Thread pool address//output: none//return: No//============================================ ====================================================void* threadpool_function (void* arg); #endif

Threadpool.c

#include "threadpool.h" struct threadpool* threadpool_init (int thread_num, int queue_max_num) {struct ThreadPool *pool    = NULL;        do {pool = malloc (sizeof (struct threadpool));            if (NULL = = Pool) {printf ("Failed to malloc threadpool!\n");        Break        } pool->thread_num = Thread_num;        Pool->queue_max_num = Queue_max_num;        Pool->queue_cur_num = 0;        Pool->head = NULL;        Pool->tail = NULL;            if (Pthread_mutex_init (& (Pool->mutex), NULL)) {printf ("Failed to init mutex!\n");        Break } if (Pthread_cond_init (& (Pool->queue_empty), NULL)) {printf ("Failed to init queue_empty!            \ n ");        Break } if (Pthread_cond_init (& (Pool->queue_not_empty), NULL)) {printf ("Failed to init queue_no            T_empty!\n ");        Break } if (Pthread_cond_init (& (Pool->queue_not_full) {printf ("Failed to init queue_not_full!\n");        Break        } pool->pthreads = malloc (sizeof (pthread_t) * thread_num);            if (NULL = = pool->pthreads) {printf ("Failed to malloc pthreads!\n");        Break        } pool->queue_close = 0;        Pool->pool_close = 0;        int i; for (i = 0; i < pool->thread_num; ++i) {pthread_create (& (Pool->pthreads[i]), NULL, THREADP        Ool_function, (void *) pool);        } return pool;        } while (0); return NULL;} int threadpool_add_job (struct threadpool* pool, void* (*callback_function) (void *arg), void *arg) {if (pool = = NULL | | call Back_function = = NULL | |    arg = = NULL) return-1;    Pthread_mutex_lock (& (Pool->mutex)); while ((Pool->queue_cur_num = = Pool->queue_max_num) &&! ( Pool->queue_close | | Pool->pool_close) {pthread_cond_wait (& (Pool->queue_not_full), & (Pool->mutex)); When the queue is full, wait for the IF (Pool->queue_close | | pool->pool_close)//queue is closed or the thread pool shuts down to exit {Pthread_mutex_unlock (        & (Pool->mutex));    return-1;    } struct Job *pjob = (struct job*) malloc (sizeof (struct job));        if (NULL = = pjob) {pthread_mutex_unlock (& (Pool->mutex));    return-1;        } pjob->callback_function = Callback_function;    Pjob->arg = arg;    Pjob->next = NULL;        if (Pool->head = = NULL) {pool->head = Pool->tail = Pjob;  Pthread_cond_broadcast (& (Pool->queue_not_empty));        When the queue is empty, a thread in the thread pool is notified when a task is available: The queue is not empty} else {pool->tail->next = Pjob;        Pool->tail = Pjob;    } pool->queue_cur_num++;    Pthread_mutex_unlock (& (Pool->mutex)); return 0;}    void* threadpool_function (void* arg) {struct ThreadPool *pool = (struct threadpool*) arg;    struct Job *pjob = NULL; while (1)//dead loop {Pthread_mutex_loCK (& (Pool->mutex)); while ((Pool->queue_cur_num = = 0) &&!pool->pool_close)//queue is empty, wait for queue non-empty {Pthread_cond_w        AIT (& (Pool->queue_not_empty), & (Pool->mutex));            if (pool->pool_close)//thread pool is closed, threads exit {Pthread_mutex_unlock (& (Pool->mutex));        Pthread_exit (NULL);        } pool->queue_cur_num--;        Pjob = pool->head;        if (Pool->queue_cur_num = = 0) {pool->head = Pool->tail = NULL;        } else {pool->head = pjob->next;        } if (Pool->queue_cur_num = = 0) {pthread_cond_signal (& (Pool->queue_empty));             The queue is empty, it is able to notify the Threadpool_destroy function, destroy the thread function} if (Pool->queue_cur_num = = pool->queue_max_num-1) {  Pthread_cond_broadcast (& (Pool->queue_not_full)); The queue is not full. will be able to notify Threadpool_add_job function, add New task} Pthread_mutex_unLock (& (Pool->mutex)); (* (pjob->callback_function))   (Pjob->arg);        The thread is really going to do the work, call the callback function free (pjob);        Pjob = NULL;    }}int Threadpool_destroy (struct ThreadPool *pool) {if (pool = = NULL) return-1;    Pthread_mutex_lock (& (Pool->mutex)); if (Pool->queue_close | | pool->pool_close)//thread pool has exited, go directly to {Pthread_mutex_unlock (& (Pool->mutex)        );    return-1;        } pool->queue_close = 1; Set Queue off flag while (pool->queue_cur_num! = 0) {pthread_cond_wait (& (Pool->queue_empty), & (Pool-&gt  ; mutex));      Wait queue is empty} pool->pool_close = 1;    Thread pool Close Flag Pthread_mutex_unlock (& (Pool->mutex));  Pthread_cond_broadcast (& (Pool->queue_not_empty));   Wake up a blocked thread in the thread pool Pthread_cond_broadcast (& (Pool->queue_not_full));    Wake-on-join task threadpool_add_job function int i; for (i = 0; i < pool->thread_num; ++i) {pthread_join (pool->pthreads[i], NULL);          Wait for all threads of thread pool to run complete} pthread_mutex_destroy (& (Pool->mutex));    Cleanup Resources Pthread_cond_destroy (& (Pool->queue_empty));       Pthread_cond_destroy (& (Pool->queue_not_empty));        Pthread_cond_destroy (& (Pool->queue_not_full));    Free (pool->pthreads);    struct Job *p;        while (pool->head! = NULL) {p = pool->head;        Pool->head = p->next;    Free (p);    } free (pool); return 0;}

3. Enter the client

watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvd2fuz3poawnozw5nmtk4mw==/font/5a6l5l2t/fontsize/400/fill/ I0jbqkfcma==/dissolve/70/gravity/center ">

Client.c

/*************************************************************************    > File name:test.c    > Author:wangzhicheng    > Mail: [email protected]     > Created time:fri from Oct 09:43:59 PM WST ************* /#include "socket.h" const char * serveraddr = "127.0.0.1"  ; #define TCPPORT 4001int Main () {int clientfd = -1;char buf[256];strcpy (buf, "1"); if (Tcpclientinit (&CLIENTFD) < 0) {perror ("Client init failed...! \ n "); exit (exit_failure);} if (Tcpclientconnect (CLIENTFD, SERVERADDR, TCPPORT)) {perror ("Can not connect to server...! \ n "); exit (exit_failure);} if (Tcpwrite (CLIENTFD, buf, strlen (buf) = = 1)) {printf ("Send successfully...! \ n ");} else printf ("Send failed...! \ n "); return 0;}

Makefile

cc=gcclibrary=. /libcflags=-i$ (LIBRARY) CXXFLAGS=OBJS1=CLIENT.O  socket.o all:client client: $ (OBJS1) $ (CC)-O   [email Protected] $ (OBJS1) SOCKET.O: $ (library)/socket.c$ (CC)-C $ (library)/socket.cclean:rm *.O client  >/dev/null 2 >&1

4. Enter the server

watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvd2fuz3poawnozw5nmtk4mw==/font/5a6l5l2t/fontsize/400/fill/ I0jbqkfcma==/dissolve/70/gravity/center ">

Server.c

/************************************************************************* > File name:server.c > Author:ma6 174 > Mail: [email protected] > Created time:sat Oct 09:46:30 PM WST ************************** /#include "socket.h" #include "threadpool.h" #define TCPPORT 4001# Define SIZE 256#define N 10int Array[n] = {1, 2, 6, 8,, 208, 222, 688, 1018};int find (int low, int. high, int m) {in T mid;if (Low <= high) {mid = (low + high) >> 1;if (array[mid] = = m) return 1;else if (Array[mid] > m) return fin D (Low, mid-1, M); else return to find (mid + 1, high, m);} return 0;} void* work (void* arg) {int *p = (int *) Arg;int m = *p;if (Find (0, N-1, m)) printf ("%d have been found...! \ n ", m), else printf ("%d have not been found...!    \ n ", m); Sleep (1);}    int main () {int serverfd =-1, clientfd = -1;char clientaddr[size];char buf[size];int num; struct ThreadPool *pool = NULL; Tcpserverinit (TCPPORT, &serverfd); if (Serverfd < 0) {perror ("Server init failed...!    \ n "); exit (exit_failure);} Pool = Threadpool_init (Ten), while (1) {tcpserverwaitconnection (SERVERFD, &AMP;CLIENTFD, clientaddr); if (clientfd < 0) {perror ("Can not connect the clients...! \ n "); exit (exit_failure);} if (Tcpblockread (CLIENTFD, buf, SIZE) <= 0) {perror ("can not read from client...! \ n "); sleep (1);}    else {num = atoi (BUF); Threadpool_add_job (pool, work, &num);}} Threadpool_destroy (pool); return 0;}

Makefile

cc=gcclibrary=. /libcflags=-i$ (LIBRARY) cxxflags=objs1=server.o  SOCKET.O threadpool.oall:serverserver: $ (OBJS1) $ (CC)-O   [ Email protected] $ (OBJS1)-LPTHREADSOCKET.O: $ (library)/socket.c$ (CC)-C $ (library)/SOCKET.CTHREADPOOL.O: $ (Library)/ threadpool.c$ (CC)-C $ (LIBRARY)/threadpool.cclean:rm *.O client  >/dev/null 2>&1
Third, test


Iv. description of the thread pool


When the thread pool is created, there are some "empty" threads in the threads pools. Without running the task, the task is organized into a task queue whenever a task is added, and the thread follows the queue team. The team tail-forward principle takes out the head task to run.

The number of tasks included in the task queue must be controlled within an upper limit. exceed the limit. The task is blocked. The thread pool is destroyed when all tasks are run out.

The Linux thread pool is simple to apply on the server

Related Article

Contact Us

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

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

A Free Trial That Lets You Build Big!

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

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

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

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