服务器示例
这里使用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; }