/***************************************** *Discription:用socket实现远程登录访问 用epoll_wait实现并发 两个端口进行通信 *socket 产生用于监听的描述符 bind 绑定地址和端口 listen 把套接字设为被动 accept()用于产生和客户机进行交 互的文件描述符 * * * * * *********************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> //inet_ntop() #include <sys/epoll.h> #define SERV_port 8000 //端口号 #define max_r 100 //存取从客户端读过来的空间 #define max_ep 10 //从内核可以处理事件集合的大小 char buf_f[1024]; int flag_fd[100]; int f_fd; int main(void) { int listenfd, connfd; char buf[100]; char buf1[100]; int r_len; char str[INET_ADDRSTRLEN]; //。。。。。。。 struct sockaddr_in servaddr, cliaddr; int ep_fd, cur_ep, accept_Count = 0; //ep_fd创建的句柄用于处理wait的epoll文件描述符 cur_ep用于记录当前epoll_wait监听事件的个数 int nfds, i, j; //epoll_wait返回的处理事件的个数 struct epoll_event ep_env; //用于注册事件 struct epoll_event events[max_ep];//用于回传要处理的事件 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); if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1){ perror("bind fail\n"); } if(listen(listenfd, 20) == -1){ perror("listen fail\n"); } printf("now we can accept connections\n"); //创建epoll句柄 并把监听socket加入epoll队列 if((ep_fd = epoll_create(1)) == -1){ perror("epoll_create fail\n"); exit(-1); } memset(flag_fd, 0, sizeof(flag_fd)); ep_env.data.fd = listenfd; ep_env.events = EPOLLIN | EPOLLET; if((epoll_ctl(ep_fd, EPOLL_CTL_ADD, listenfd, &ep_env)) == -1){ perror("epoll_ctl fail\n"); } //把服务器标准输入加入epoll队列 ep_env.data.fd = STDIN_FILENO; ep_env.events = EPOLLIN | EPOLLET; if((epoll_ctl(ep_fd, EPOLL_CTL_ADD, STDIN_FILENO, &ep_env)) == -1){ perror("epoll_ctl fail\n"); } flag_fd[listenfd] = 1; flag_fd[STDIN_FILENO] = 1; printf("epoll_server start server port:%d\n", SERV_port); cur_ep = 2; while(1){ nfds = epoll_wait(ep_fd, events, cur_ep, -1); for(i = 0; i < nfds; i++){ if(events[i].data.fd == listenfd){ int cliaddr_len = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); sprintf(buf, "accept from %s at port %d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); printf("%d:%s", ++accept_Count, buf); ep_env.events = EPOLLIN | EPOLLET; ep_env.data.fd = connfd; epoll_ctl(ep_fd, EPOLL_CTL_ADD, connfd, &ep_env); flag_fd[connfd] = 1; cur_ep++; continue; } else if(events[i].data.fd == STDIN_FILENO){ if(handle(events[i].data.fd, connfd) < 0) { epoll_ctl(ep_fd, EPOLL_CTL_DEL, j, &ep_env); close(events[i].data.fd); cur_ep--; flag_fd[events[i].data.fd] = 0; } } else{ if(handle(events[i].data.fd, STDIN_FILENO) < 0){ epoll_ctl(ep_fd, EPOLL_CTL_DEL, connfd, &ep_env); close(events[i].data.fd); cur_ep--; flag_fd[events[i].data.fd] = 0; } } } /* int cliaddr_len = sizeof(cliaddr); while((r_len = read(connfd, buf, max_r))){ printf("received from %s at port %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port)); write(connfd, buf, r_len); }*/ } close(listenfd); return 0; } //从src复制到dest int handle(int src, int dest) { int nread; int j; char buf[1024]; nread = read(src, buf, 1024); if(nread == 0){ printf("client close the connection\n"); return -1; } if(nread < 0){ perror("read error"); return -1; } for(j = 0; j < 100; j++) if(j != 3 && j != src && flag_fd[j] == 1) write(j, buf, nread); return 0; }