epoll使用

服务端:

#include <stdio.h>
#include <sys/epoll.h>
#include <queue>
#include <iostream>
#include <semaphore.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>

using namespace std;

#define THREAD_NUM 80
#define LISTEN_MAX 100
#define EPOLL_CREATE_FDS 100000
#define EPOLL_WAIT_EVENTS 100
#define WORK_THREADS_MAX 20

sem_t g_sem;
int g_epfd;
int g_conncount = 0;

struct myepoll_buf
{
	int iTime;
	char szBuf[100];
};

struct myepoll_data
{
	int fd;
	struct myepoll_buf *pbuf;
};

queue<struct epoll_event *> g_TaskQueue; 
pthread_mutex_t g_mutex;
pthread_t pthreadID[WORK_THREADS_MAX];

void * workfunc(void *arg)
{
	int listenfd = (int)arg;
	struct epoll_event *pev, ev;
	int ilen;
	socklen_t client_len;
	struct sockaddr_in clientaddr;
	int connfd;
	int old;
	char szData[100], szTime[2] = {0};
	int iTime;
	struct myepoll_data *pData;
	

	while (1)
	{
		sem_wait(&g_sem);
	
		pthread_mutex_lock(&g_mutex);
		pev = g_TaskQueue.front();
		g_TaskQueue.pop();
		pthread_mutex_unlock(&g_mutex);
		if (pev->data.fd == listenfd)  //连接请求
		{
			while ((connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &client_len)) > 0)
			{
				printf("总连接数:%d\n", ++g_conncount);
				old = fcntl(connfd, F_GETFL);
				old = old | O_NONBLOCK;
				fcntl(connfd, F_SETFL, old);
				printf("接收了来自[%s:%d]的请求\n",inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
				struct myepoll_data *pData = (struct myepoll_data *)malloc(sizeof(struct myepoll_data));
				pData->fd = connfd;
				pData->pbuf = NULL;
				ev.data.ptr = pData;
				ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
				epoll_ctl(g_epfd, EPOLL_CTL_ADD, connfd, &ev);
			}
		}
		else if (pev->events & EPOLLIN) //读
		{
			pData = (struct myepoll_data *)pev->data.ptr;
			if (pData == NULL)
				continue;

			memset(szData, 0, sizeof (szData));
			ilen = read(pData->fd, szData, 100);
			if (ilen <= 0)  //连接断开
			{
				printf("连接断开\n");
				if (pData->pbuf)
					free(pData->pbuf);
				pData->pbuf = NULL;
				
				epoll_ctl(g_epfd, EPOLL_CTL_DEL, pData->fd, NULL);
				close(pData->fd);
				free(pData);
				pData = NULL;
				continue;
			}
			printf("接收到客户端发送的数据:%s\n", szData);
			memcpy(szTime, szData, 1);
			szTime[1] = '\0';
			iTime = atoi(szTime);

			if (!pData->pbuf)
			{
				pData->pbuf = (struct myepoll_buf *)malloc(sizeof (struct myepoll_buf));		
				if (pData->pbuf == NULL)
				{
					printf("out of memory!\n");
					continue;
				}
			}

			pData->pbuf->iTime = iTime;
			sprintf(pData->pbuf->szBuf, "(%s)请求完成,耗时%d", szData, iTime);
			ev.events = EPOLLOUT | EPOLLET | EPOLLRDHUP;
			ev.data.ptr = pData;
			epoll_ctl(g_epfd, EPOLL_CTL_MOD, pData->fd, &ev);
		}
		else if (pev->events & EPOLLOUT)  //写
		{
			pData = (struct myepoll_data *)pev->data.ptr;
			if (pData == NULL)
				continue;

			if (pData->pbuf)
			{
				//sleep(pData->pbuf->iTime);
			}
			else
			{
				epoll_ctl(g_epfd, EPOLL_CTL_DEL, pData->fd, NULL);
				close(pData->fd);
				free(pData);
				continue;
			}
			write(pData->fd, pData->pbuf->szBuf, strlen(pData->pbuf->szBuf) + 1);
			printf("请求处理完成,发送结果:%s\n", pData->pbuf->szBuf);
			free(pData->pbuf);
			pData->pbuf = NULL;
			ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
			ev.data.ptr = pData;
			epoll_ctl(g_epfd, EPOLL_CTL_MOD, pData->fd, &ev);
		}
		else if (pev->events & EPOLLRDHUP)  //连接关闭
		{
			pData = (struct myepoll_data *)pev->data.ptr;
			if (pData != NULL)
			{
				printf("关闭连接,socket:%d\n", pData->fd);
				epoll_ctl(g_epfd, EPOLL_CTL_DEL, pData->fd, NULL);
				close(pData->fd);
				if (pData->pbuf)
					free(pData->pbuf);
				pData->pbuf = NULL;
				free(pData);	
				pData = NULL;
			}
		}
	}
}

int main(int argc, char **argv)
{
	int iPort = 8888;
	char szIp[20] = "127.0.0.1";

	if (2 == argc)
	{
		if ((iPort = atoi(argv[1])) < 0)
		{
			fprintf(stderr, "端口[%s]不正确!\n", argv[1]);
			return 1;
		}
	}	
	else if (3 == argc)
	{
		if ((iPort = atoi(argv[1])) < 0)
        {
            fprintf(stderr, "端口[%s]不正确!\n", argv[1]);
            return 1;
        }
		
		sprintf(szIp, "%s", argv[2]);
	}
	
	int listenfd, i;
	struct sockaddr_in serveraddr;
	struct epoll_event ev;
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	int old = fcntl(listenfd, F_GETFL);
	old = old | O_NONBLOCK;
	fcntl(listenfd, F_SETFL, old);
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr(szIp);
	serveraddr.sin_port = htons(iPort);
	if (-1 == bind(listenfd, (struct sockaddr *)&serveraddr, sizeof (serveraddr)))
	{
		printf("bind()失败!IP:%s, port:%d\n", szIp, iPort);
		return 1;
	}
	else
		printf("绑定成功,socket:%d\n", listenfd);

	if (-1 == listen(listenfd, LISTEN_MAX))
	{
		printf("listen()失败!");
		return 1;
	}
	else
		printf("监听成功,socket:%d\n", listenfd);

	if (sem_init(&g_sem, 0, 0) < 0)
	{
		printf("sem_init()失败!\n");
		return 1;
	}

	if (pthread_mutex_init(&g_mutex, NULL) < 0)
	{
		printf("pthread_mutex_init()失败!\n");
		return 1;
	}
	
	
	for (i = 0; i < WORK_THREADS_MAX; ++i)
		pthread_create(pthreadID + i, NULL, workfunc, (void *)listenfd);
	
	struct epoll_event events[EPOLL_WAIT_EVENTS];

	g_epfd = epoll_create(EPOLL_CREATE_FDS);
	ev.data.fd = listenfd;
	ev.events = EPOLLIN | EPOLLET;
	epoll_ctl(g_epfd, EPOLL_CTL_ADD, listenfd, &ev);

	while (1)
	{
		int iFds = epoll_wait(g_epfd, events, EPOLL_WAIT_EVENTS, -1);
		if (iFds < 0)
			break;
		
		for (i = 0; i < iFds; ++i)
		{
			struct epoll_event *pev = (struct epoll_event *)malloc(sizeof (struct epoll_event));
			memcpy(pev, &events[i], sizeof (struct epoll_event));

			pthread_mutex_lock(&g_mutex);
			g_TaskQueue.push(pev);
			pthread_mutex_unlock(&g_mutex);
			sem_post(&g_sem);
		}
	}

	for (i = 0; i < WORK_THREADS_MAX; ++i)
		pthread_join(pthreadID[i], NULL);

	pthread_mutex_destroy(&g_mutex);
	sem_destroy(&g_sem);
	close(g_epfd);
	

	return 0;
}

测试客户端:

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

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8888

int Random(int start, int end)
{
	srand(time(NULL));
	int dis = end - start;
	return rand() % dis + start;
}

void * workfunc(void *arg)
{
	int iTime;
	char szBuf[100];
	int iReq = (int)arg;
	int iret = 0;
	struct sockaddr_in serveraddr;
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr(SERVER_IP);
	serveraddr.sin_port = htons(SERVER_PORT);
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	while (connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) 
	{
		printf("连接服务器失败,稍后重试!Err:%d\n", errno);
		sleep(1);
	}
	for (int i = 0; i < iReq; ++i)
	{
		sprintf(szBuf, "%d线程[%u]发送第%d次请求", Random(0, 10), pthread_self(), i);
		printf("%s\n", szBuf);
		iret = write(sockfd, szBuf, strlen(szBuf) + 1);
		printf("发送数据长度:%d\n", iret);
		memset(szBuf, 0, 100);
		read(sockfd, szBuf, 100);
		printf("接收返回结果:%s\n", szBuf);
	}
	printf("线程[%u]请求结束,关闭socket[%d]\n", pthread_self(), sockfd);
	close(sockfd);
}

int main(int argc, char **argv)
{
	if (argc <3)
	{
		printf("请提供两个参数,例如:程序 线程数 请求数\n");
		return 1;
	}

	int iThreads = atoi(argv[1]);
	int iReq = atoi(argv[2]);
	int i;
	int ifailed = 0;
	pthread_t *pThreadID = (pthread_t *)malloc(iThreads * sizeof(pthread_t));
	memset(pThreadID, 0, sizeof (pthread_t) * iThreads);
	for (i = 0; i < iThreads; i++)
	{
		if (0 != pthread_create(pThreadID + i, NULL, workfunc, (void *)iReq))
		{
			printf("创建线程失败!Err:%d\n", errno);
			++ifailed;
		}
	}

	for (i = 0; i < iThreads; ++i)
	{
		if (pThreadID[i] == 0)
			continue;
		pthread_join(*(pThreadID + i), NULL);
	}

	printf("创建线程失败数:%d\n", ifailed);
	free(pThreadID);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vfdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值