高并发服务器编程之epoll(二)

服务器示例

这里使用epoll_data联合体中的ptr指针。

fd的使用链接:epoll_data.fd

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>

#define MAX_SIZE 5

typedef struct client_info
{
	int fd;
	struct in_addr addr;
	int port;
}client_info;


int main(int argc, char *argv[])
{
	int server_fd;
	int ret;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	int client_fd;
	server_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (server_fd < 0){
		perror("socket error");
		return -1;
	}
	
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(9000);
	server_addr.sin_addr.s_addr = inet_addr("192.168.121.128");

	int len = sizeof(struct sockaddr_in);
	ret = bind(server_fd, (struct sockaddr*)&server_addr, len);
	if (ret == -1){
		perror("bind error");
		return -1;
	}
	ret = listen(server_fd, MAX_SIZE);
	if (ret < 0){
		perror("listen error");
		return -1;
	}
	int epoll_fd, nfds = 0, i = 0;
	struct epoll_event ev, evs[MAX_SIZE];
	//创建一个epoll监听集合
	epoll_fd = epoll_create(MAX_SIZE);
	client_info *pci = NULL;
	pci = (client_info*)malloc(sizeof(client_info));
	pci->fd = server_fd;
	memcpy(&pci->addr, &server_addr.sin_addr, sizeof(struct in_addr));
	pci->port = 0;
	ev.events = EPOLLIN | EPOLLET;
	ev.data.ptr = pci;
	//将监听socket描述符与定义好的事件添加到epoll监听集合中
	if ((epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev)) < 0){
		perror("epoll_ctl add error");
		return -1;
	}
	for (i = 0;i<MAX_SIZE;i++){
		evs[i].data.ptr = NULL;
	}
	char buff[1024] = {0};
	while (1){
		//epoll阻塞等待事件触发,当某个描述符触发事件,则将触发的事件写入到evs中
		//并且返回触发事件的描述符个数nfds
		nfds = epoll_wait(epoll_fd, evs, MAX_SIZE, 3000);
		if (nfds < 0){
			//epoll等待出错
			perror("epoll_wait error");
			continue;
		}else if (nfds == 0){
			//3000毫秒内没有任何描述符触发事件
			printf("timeout\n");
			continue;
		}
		//循环从evs中取出触发的事件
		for (i = 0;i<nfds;i++){
			//如果evs[i].data.fd == sockfd,代表客户端请求通道有客户端请求到来
			//则接受客户端连接请求
			pci = evs[i].data.ptr;
			if (pci->fd == server_fd){
				client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &len);
				if (client_fd < 0){
					perror("new client error");
					continue;
				}
				printf("new accept----[%s:%d]\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
				pci = (client_info*)malloc(sizeof(client_info));
				pci->fd = client_fd;
				memcpy(&pci->addr, &client_addr.sin_addr, sizeof(struct in_addr));
				pci->port = ntohs(client_addr.sin_port);
				ev.events = EPOLLIN | EPOLLET;
				ev.data.ptr = pci;
				//add event
				ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev);
				if (ret < 0){
					perror("epoll_ctl add error");
				}
				//EPOLLIN代表可读事件
			}else if (evs[i].events & EPOLLIN){
				//代表有其他数据传输,则接受数据
				memset(buff, 0x00, 1024);
				ret = recv(pci->fd, buff, 1024, 0);
				if (ret <= 0){
					//ret == 0代表对端断开了tcp连接
					//ret < 0 出错
					//EINTR被信号打断出错
					//EAGAIN描述符没有准备好
					if (errno == EAGAIN || errno == EINTR){
						continue;
					}
					//除了上面2个错误之外则从监听集合中删除描述符并关闭socket
					if ((epoll_ctl(epoll_fd, EPOLL_CTL_DEL, pci->fd, &ev)) < 0){
						perror("epoll_ctl del error");
					}
					close(pci->fd);
				}
				printf("%s----[%s:%d]\n", buff, inet_ntoa(pci->addr), pci->port);
			}
		}
	}
	close(server_fd);
	free(pci);
	return 0;
}

客户端示例


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



int main(int argc, char *argv[])
{
	int sockfd;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	int ret;
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0){
		perror("socket error");
		return -1;
	}
	int KeepAlive=1;
	socklen_t KPlen=sizeof(int); 
	if(setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,(char *)&KeepAlive,KPlen)!=0){ 
		perror("setsockopt error"); 
		return -1;
	} 
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(9000);
	server_addr.sin_addr.s_addr = inet_addr("192.168.121.128");

	client_addr.sin_family = AF_INET;
	client_addr.sin_port = htons(8000);
	client_addr.sin_addr.s_addr = inet_addr("192.168.121.128");

	int len = sizeof(struct sockaddr_in);
	ret = bind(sockfd, (struct sockaddr*)&client_addr, len);
	if (ret == -1){
		perror("bind error");
		return -1;
	}

	ret = connect(sockfd, (struct sockaddr*)&server_addr, len);
	if (ret < 0){
		perror("connect error");
		return -1;
	}
	
	char buff[1024] = {0};
	int i = 0;
	while (1){
		memset(buff, 0x00, 1024);
		sprintf(buff, "test1");
		send(sockfd, buff, 1024, 0);
		sleep(1);
	}
	close(sockfd);
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_33408113/article/details/80197589