IO模型epoll

通过epoll实现一个并发服务器

服务器
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//int recv_runm(int newfd, struct sockaddr_in cin);
#define ERR_MSG(msg)                  \
	{                                 \
		printf("__%d__\n", __LINE__); \
		perror(msg);                  \
	}
#define IP "192.168.250.100"
#define PORT 12345

int main(int argc, const char *argv[])
{
	struct epoll_event event;
	struct epoll_event events[10]; // 存放就绪事件描述符的数组
	// 创建流式套接字
	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sfd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}
	printf("socket success\n");

	// 允许端口快速被复用
	int reuse = 1;
	if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		ERR_MSG("setsockopt");
		return -1;
	}

	// 绑定服务器的IP和端口
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PORT);
	sin.sin_addr.s_addr = inet_addr(IP);

	if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
	{
		ERR_MSG("bind");
		return -1;
	}
	printf("bind success\n");
	// 将套接字设置为被动监听状态
	if (listen(sfd, 128) < 0)
	{
		ERR_MSG("listen");
		return -1;
	}
	printf("listen success\n");
	// 获取链接成功后的套接字,拿到文件描述符
	struct sockaddr_in cin;
	struct sockaddr_in savecin[1024];
	socklen_t len = sizeof(cin);
	char s[128] = "";
	char s1[128] = "hello";
	ssize_t res = 0;
	printf("__%d__\n", __LINE__);

	int num;
	int newfd, epfd;
	printf("__%d__\n", __LINE__);
	epfd = epoll_create(1);
	if (epfd < 0)
	{
		printf("epoll_create filed\n");
		exit(-1);
	}
	// 将套接字添加到红黑树
	event.events = EPOLLIN;
	event.data.fd = sfd;
	if (epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &event) < 0)
	{
		printf("epoll_ctl add filed\n");
	}
	printf("__%d__\n", __LINE__);
	while (1)
	{
		int i;
		printf("__%d__\n", __LINE__);
		int ret = epoll_wait(epfd, events, 10, -1);
		if (ret < 0)
		{
			printf("epoll_wait filed\n");
			exit(-1);
		}
		printf("__%d__\n", __LINE__);

		for (i = 0; i < ret; i++)
		{

			if (events[i].data.fd == sfd)
			{
				printf("__%d__\n", __LINE__);
				newfd = accept(sfd, (struct sockaddr *)&cin, &len);
				if (newfd < 0)
				{
					ERR_MSG("accept");
					return -1;
				}
				printf("accept success\n");
				savecin[newfd] = cin;
				// 添加准备就绪事件进入epoll;
				event.events = EPOLLIN; // 读事件
				event.data.fd = newfd;
				if (epoll_ctl(epfd, EPOLL_CTL_ADD, newfd, &event) < 0)
				{
					printf("epoll_ctl add filed\n");
				}
			}
			else
			{
				if (events[i].events & EPOLLIN)
				{ // printf("__%d__\n",__LINE__);
					// 获取信息
					int fd1=events[i].data.fd;
					bzero(s, sizeof(s));
					res = recvfrom(events[i].data.fd, s, sizeof(s), 0, NULL, NULL);
					if (0 == res)
					{
						printf("客户端关闭\n");
						close(i);
						if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd1, &event) < 0)
						{
							printf("epoll_ctl sub filed\n");
						}
					}
					else if (res < 0)
					{
						ERR_MSG("recv");
						return -1;
					}
					printf("%s  %d:%s\n", inet_ntoa(savecin[i].sin_addr), ntohs(savecin[i].sin_port), s);
				}
			}
		}
	}

	if (close(sfd) < 0)
	{
		ERR_MSG("close");
		return -1;
	}
	return 0;
}



客户端
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define ERR(msg)                      \
	{                                 \
		printf("__%d__\n", __LINE__); \
		perror(msg);                  \
		return -1;                    \
	}
#define PORT 12345
#define IP "192.168.250.100"

int main(int argc, const char *argv[])
{
	//struct epoll_event event;
	//struct epoll_event events[10]; // 存放就绪事件描述符的数组
	// 创建套接字
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd < 0)
	{
		ERR("socket");
	}
	printf("socket success\n");

	// 连接服务器
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PORT);
	sin.sin_addr.s_addr = inet_addr(IP);
	socklen_t len = sizeof(sin);

	if (connect(fd, (struct sockaddr *)&sin, len) < 0)
	{
		ERR("connect");
	}
	printf("connect success\n");

	// 读取数据
	char s[128] = "";
	char s1[128] = "";
	ssize_t res = 0;
	int num;
	int epfd;

	/*epfd = epoll_create(1);
	if (epfd < 0)
	{
		printf("epoll_create filed\n");
		exit(-1);
	}
	// 将套接字添加到红黑树
	
	event.data.fd = fd;
	if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event) < 0)
	{
		printf("epoll_ctl add filed\n");
	}
	event.data.fd = 0;
	if (epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &event) < 0)
	{
		printf("epoll_ctl 0 add filed\n");
	}
*/
	while (1)
	{
		/*printf("__%d__\n", __LINE__);
		int i;
		num = epoll_wait(epfd, events, 10, -1);
		printf("__%d__\n", __LINE__);
		if (num < 0)
		{
			ERR("select");
		}
		else if (0 == num)
		{
			printf("超时\n");
		}
		printf("__%d__\n", __LINE__);
		for (i = 0; i < num; i++)
		{
			if (events[i].data.fd == 0)
			{*/
				printf("请输入要发送的内容:");
				scanf("%s", s1);
				if (write(fd, s1, sizeof(s1)) < 0)
				{
					ERR("write");
				}
				printf("发送成功\n");
			/*}
			printf("__%d__\n", __LINE__);
			if (events[i].data.fd == fd)
			{
				// 发送数据
				printf("__%d__\n", __LINE__);
				bzero(s, sizeof(s));
				res = read(fd, s, sizeof(s));
				if (res < 0)
				{
					ERR("read");
				}
				else if (0 == res)
				{
					printf("对端服务器关闭\n");
					break;
				}
				printf("%s\n", s);
			}
		}*/
	}

	if (close(fd) < 0)
	{
		ERR("close");
	}

	return 0;
}

IO模型epoll_第1张图片

 

你可能感兴趣的:(算法)