epoll+multithreading

#include <cstdlib>
#include <iostream>
#include <memory>
#include <thread>
#include <mutex>
#include <future>
#include <atomic>
#include <queue>
#include <vector>
#include <utility>
#include <functional>


template <typename T, typename...Args>
class thread_safe_queue
{
private:
	using fun_type = std::function<T(Args...)>;
	std::mutex mut;
	std::queue<fun_type> data_queue;
	std::condition_variable data_cond;
public:
	thread_safe_queue() {}
	template<typename C>
	void push(C&& new_value)
	{
		std::lock_guard<std::mutex> lk(mut);
		data_queue.push(std::move(new_value));
		data_cond.notify_one();
	}
	template<typename C>
	void wait_and_pop(C&& value)
	{
		std::unique_lock<std::mutex> lk(mut);
		data_cond.wait(lk, [this] {return !data_queue.empty(); });
		value = std::move(data_queue.front());
		data_queue.pop();
	}
	template<typename C>
	std::shared_ptr<C> wait_and_pop()
	{
		std::unique_lock<std::mutex> lk(mut);
		data_cond.wait(lk, [this] {return !data_queue.empty(); });
		std::shared_ptr<C> res(std::make_shared<T>(std::move(data_queue.front())));
		data_queue.pop();
		return res;
	}

	bool try_pop(fun_type& value)
	{
		std::lock_guard<std::mutex> lk(mut);
		if (data_queue.empty())
			return false;
		value = std::move(data_queue.front());
		data_queue.pop();
		return true;
	}
	template<typename C>
	std::shared_ptr<C> try_pop()
	{
		std::lock_guard<std::mutex> lk(mut);
		if (data_queue.empty())
			return std::shared_ptr<C>();
		std::shared_ptr<C> res(std::make_shared<C>(std::move(data_queue.front())));
		data_queue.pop();
		return res;
	}

	bool empty()
	{
		std::lock_guard<std::mutex> lk(mut);
		return data_queue.empty();
	}
};

class join_threads
{
	std::vector<std::thread>& threads;
public:
	explicit join_threads(std::vector<std::thread>& threads_) :
		threads(threads_)
	{ }
	~join_threads()
	{
		for (unsigned long i = 0; i < threads.size(); i++)
		{
			if (threads[i].joinable())
				threads[i].join();
		}
	}
};
template<typename R, typename ...Args>
class thread_pool
{
private:
	std::atomic_bool done;
	thread_safe_queue<R, Args... > work_queue;
	std::vector <std::shared_ptr<std::thread>> threads;
	//join_threads join
public:
	void worker_thread(Args&&...args)
	{

		while (!done)
		{
			std::function<R(Args...)>task;
			if (work_queue.try_pop(task))
			{

				task(std::move(args)...);
			}
			else
			{
				std::this_thread::yield();
			}
		}
	}

public:
	thread_pool() { done = false; }

	void start(Args...args)
	{
		unsigned const thread_count = std::thread::hardware_concurrency();
		try
		{
			for (unsigned i = 0; i < thread_count; ++i)
			{
				threads.emplace_back(std::make_shared<std::thread>(&thread_pool<R, Args...>::worker_thread, this, args...));
			}
		}
		catch (...)
		{
			done = true;
			throw;

		}
	}

	~thread_pool()
	{
		done = true;
		for (unsigned long i = 0; i < threads.size(); i++)
		{
			if (threads[i]->joinable())
				threads[i]->join();
		}
	}


	
	void sumit(std::function<R(Args...)>(f))
	{
		work_queue.push(std::function<R(Args...)>(f));
	}
	//rest as before
};
//int fun(int i)
//{
//	std::cout << "good,works!" << "1" << std::endl;
//	return 6;
//}
//void fun2(int i, char c, double d)
//{
//	std::cout << i << " " << c << " " << d << std::endl;

//}


//int main()
//{
//	thread_pool<void, int, char, double > p ;
//	p.sumit(fun2);
//	p.start(1,'2',3.999);
//	return 0;
//}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <ctype.h>
#include <iostream>
#include "thread_pool_args.h"
 
#define MAXLINE 8192

#define OPEN_MAX 5000
#define SERV_PORT 8000

thread_pool<void,int,char*,int> pool;


void handle_function(int sockfd,char* buffer, int n)
{
   for(int i = 0; i < n; i++)
     buffer[i] = toupper(buffer[i]);
    
    write(STDOUT_FILENO, buffer,n);
    write(sockfd, buffer,n);

}

void perr_exit(const char *s)
{
	perror(s);
	exit(-1);
}


int main(int argc, char *argv[])
{
    int  listenfd, connfd,sockfd;
    int  i, n, num = 0;
    ssize_t nready, efd, res;
    char  str[INET_ADDRSTRLEN],buffer[MAXLINE];
    socklen_t clilen;	
	
    struct sockaddr_in cliaddr, servaddr;
    struct epoll_event tep, ep[OPEN_MAX];       //tep: epoll_ctl參數  ep[] : epoll_wait參數
 
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
 
    int opt = 1;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));      //端口複用
 
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);
 
    bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
 
    listen(listenfd, 20);
 
    efd = epoll_create(OPEN_MAX);               //創建epoll模型, efd指向紅黑樹根節點
    if (efd == -1)
        perr_exit("epoll_create error");
 
    tep.events = EPOLLIN; tep.data.fd = listenfd;           //指定lfd的監聽時間爲"讀"
    res = epoll_ctl(efd, EPOLL_CTL_ADD, listenfd, &tep);    //將lfd及對應的結構體設置到樹上,efd可找到該樹
    if (res == -1)
        perr_exit("epoll_ctl error");
 
    for ( ; ; ) {
        /*epoll爲server阻塞監聽事件, ep爲struct epoll_event類型數組, OPEN_MAX爲數組容量, -1表永久阻塞*/
        nready = epoll_wait(efd, ep, OPEN_MAX, -1); 
        if (nready == -1)
            perr_exit("epoll_wait error");
 
        for (i = 0; i < nready; i++) {
            if (!(ep[i].events & EPOLLIN))      //如果不是"讀"事件, 繼續循環
                continue;
 
            if (ep[i].data.fd == listenfd) {    //判斷滿足事件的fd是不是lfd            
                clilen = sizeof(cliaddr);
                connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);    //接受鏈接
 
                printf("received from %s at PORT %d\n", 
                        inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), 
                        ntohs(cliaddr.sin_port));
                printf("cfd %d---client %d\n", connfd, ++num);
 
                tep.events = EPOLLIN; tep.data.fd = connfd;
                res = epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &tep);
                if (res == -1)
                    perr_exit("epoll_ctl error");
 
            } else {                                //不是lfd, 
                sockfd = ep[i].data.fd;
                n = read(sockfd, buffer, MAXLINE);
 
                if (n == 0) {                       //讀到0,說明客戶端關閉鏈接
                    res = epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL);  //將該文件描述符從紅黑樹摘除
                    if (res == -1)
                        perr_exit("epoll_ctl error");
                    close(sockfd);                  //關閉與該客戶端的鏈接
                    printf("client[%d] closed connection\n", sockfd);
 
                } else if (n < 0) {                 //出錯
                    perror("read n < 0 error: ");
                    res = epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL);
                    close(sockfd);
 
                } else { 
                    pool.sumit(handle_function);
                    pool.start(sockfd,buffer,n) ;                          //實際讀到了字節數
                }
            }
        }
    }
    close(listenfd);
    close(efd);
 
    return 0;
}

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#define   REQUEST 400
#define   REPLY   400
 
#define   UDP_SERV_PORT  7777
#define   TCP_SERV_PORT  8000

using namespace std;

int main(int argc, char *argv[])
{
 
    struct  sockaddr_in serv;
    char    request[REQUEST] = {'\0'}, reply[REPLY]={'\0'};
    int     sockfd;
    int     nleft, nread;
    strcpy(request,"test\n");
    strcpy(reply,"good,well,better,best\n");
   // if(argc != 2)
    //    cerr<<"usage: tcpcli <IP address of server>"<<endl;
 
    if((sockfd = socket(PF_INET,SOCK_STREAM,0)) < 0)
        cerr<<"socket error"<<endl;
    memset(&serv,0,sizeof (serv));
    serv.sin_family = AF_INET;
    serv.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv.sin_port = htons(TCP_SERV_PORT);
 

    if((connect(sockfd,(struct sockaddr*)&serv,sizeof(serv)) )< 0)
        cerr<<"connect error"<<endl;
 
    if( write(sockfd,request,REQUEST) != REQUEST)
        cerr<<"write error"<<endl;
 
    nleft = REPLY;
    const char* ptr = reply;
 
    while (nleft > 0) {
      
        if((nread = write(sockfd,(char*)ptr,REPLY) ) < 0)
            return  nread;
        else if (nread == 0)
            break;
        nleft -= nread;
        ptr += nread;
    }
    

   close(sockfd);
     return 0;
}

while true ;do "hello"; sleep 2; done; 

while true; do command; sleep 2; done;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章