<span style="font-size:18px;"><span style="font-size:18px;">server.c: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/select.h> #include <errno.h> #include <sys/epoll.h> #include <fcntl.h> #define SERVER_IP "127.0.0.1" #define SERVER_PORT 8000 #define MAX_RECV_LEN 1024 #define MAX_CLIENT_NUM 30 #define MAX_EVENT MAX_CLIENT_NUM</span> #define BACK_LOG 20 static int running = 1; int set_non_block (int fd) { int flags, s; flags = fcntl (fd, F_GETFL, 0); if (flags == -1) { perror ("fcntl"); return -1; } flags |= O_NONBLOCK; s = fcntl (fd, F_SETFL, flags); if (s == -1) { perror ("fcntl"); return -1; } return 0; } int main (int argc, char *argv[])</span> { <span style="white-space:pre"> </span>int sock_fd = -1; int ret = -1; struct sockaddr_in serv_addr; struct sockaddr_in cli_addr; socklen_t serv_addr_len = 0; socklen_t cli_addr_len = 0; char recv_buf[MAX_RECV_LEN]; int new_conn_fd = -1; int i = 0; int max_fd = -1; int num = -1; int ep_fd = -1; memset (&serv_addr, 0, sizeof (serv_addr)); memset (&cli_addr, 0, sizeof (cli_addr)); sock_fd = socket (AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) { perror ("Fail to socket"); exit (1); } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons (SERVER_PORT); serv_addr.sin_addr.s_addr = inet_addr (SERVER_IP); unsigned int value = 1; if (setsockopt (sock_fd, SOL_SOCKET, SO_REUSEADDR, (void *) &value, sizeof (value)) < 0) { perror ("Fail to setsockopt"); exit (1); } serv_addr_len = sizeof (serv_addr); if (bind (sock_fd, (struct sockaddr *) &serv_addr, serv_addr_len) < 0) { perror ("Fail to bind"); exit (1); } if (listen (sock_fd, BACK_LOG) < 0) { perror ("Fail to listen"); exit (1); } set_non_block (sock_fd);//epoll使用边缘触发模式时要将监听的描述符设置成非阻塞 ep_fd = epoll_create (MAX_EVENT);//epoll建立 if (ep_fd < 0) { perror ("Fail to epoll_create"); exit (1); } struct epoll_event ev, ev_ready[MAX_EVENT]; bzero (&ev, sizeof (ev)); ev.data.fd = sock_fd; ev.events = EPOLLIN | EPOLLET; ret = epoll_ctl (ep_fd, EPOLL_CTL_ADD, sock_fd, &ev);//加入监听描述符 if (ret < 0) { perror ("Fail to epoll_ctl"); exit (1); } char buf[1024]; int len; int timeout = 5000; //ms while (running) { bzero (&ev_ready, sizeof (ev_ready)); ret = epoll_wait (ep_fd, ev_ready, MAX_EVENT, timeout); if (ret == 0) { printf ("timeout\n"); } else if (ret < 0) { printf ("error occur\n"); } else { for (i = 0; i < ret; i++) { if (ev_ready[i].data.fd == sock_fd) { printf ("new client comes\n"); len = sizeof (cli_addr); new_conn_fd = accept (sock_fd, (struct sockaddr *) &cli_addr, &len); if (new_conn_fd < 0) { perror ("Fail to accept"); exit (1); } else { set_non_block (new_conn_fd); ev.data.fd = new_conn_fd; ev.events = EPOLLIN | EPOLLET; epoll_ctl (ep_fd, EPOLL_CTL_ADD, new_conn_fd, &ev); } } else { if (ev_ready[i].events & EPOLLIN) { int fd = ev_ready[i].data.fd; memset (recv_buf, 0, MAX_RECV_LEN); { num = read (fd, recv_buf, MAX_RECV_LEN); if (num < 0) { printf ("Client(%d) left\n", fd); ev.data.fd = fd; ev.events = EPOLLIN | EPOLLET; epoll_ctl (ep_fd, EPOLL_CTL_DEL, fd, &ev); close (fd); } else if (num > 0) { recv_buf[num] = '\0'; printf ("Recieve client(%d) data\n", fd); printf ("Data: %s\n\n", recv_buf); } if (num == 0) { printf ("Client(%d) exit\n", fd); ev.data.fd = fd; ev.events = EPOLLIN | EPOLLET; epoll_ctl (ep_fd, EPOLL_CTL_DEL, fd, &ev);//删除描述符 close (fd); } } } } } } } return 0; } client.c: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/select.h> #define SERVER_IP "127.0.0.1" #define SERVER_PORT 8000 #define MAX_RECV_LEN 1024 static int running = 1; int main (int argc, char *argv[]) { int sock_fd = -1; int ret = -1; struct sockaddr_in serv_addr; struct sockaddr_in cli_addr; socklen_t serv_addr_len = 0; memset (&serv_addr, 0, sizeof (serv_addr)); sock_fd = socket (AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) { perror ("Fail to socket"); exit (1); } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons (SERVER_PORT); serv_addr.sin_addr.s_addr = inet_addr (SERVER_IP); serv_addr_len = sizeof (serv_addr); if (connect (sock_fd, (struct sockaddr *) &serv_addr, serv_addr_len) < 0) { perror ("Fail to connect"); exit (1); } char buf[1024]; int num = 0; while (running) { num = read (STDIN_FILENO, buf, MAX_RECV_LEN); if (num > 0) { buf[num] = '\0'; printf ("buf: %s\n", buf); num = write (sock_fd, buf, num); if (num < 0) { printf ("write failed\n"); exit (1); } if (strncmp (buf, "exit", strlen ("exit")) == 0) { printf ("Client exit\n"); close (sock_fd); return 0; } } } return 0; } Makefile: all: client server gcc -o client client.c gcc -o server server.c </span></span>
服务端log:
timeout
new client comes
Recieve client(5) data
Data: hello
timeout
new client comes
timeout
Recieve client(6) data
Data: hello
timeout
Client(6) exit
timeout
new client comes
timeout
Client(5) exit
timeout