udp tcp epoll serv
[socket_samples.git] / epoll / serv.c
blob13bb9e7e6268785700e512f91ca91ac6bd6f0b52
1 #include <sys/socket.h>
2 #include <sys/wait.h>
3 #include <netinet/in.h>
4 #include <netinet/tcp.h>
5 #include <sys/epoll.h>
6 #include <sys/sendfile.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <fcntl.h>
14 #include <errno.h>
16 #define MAX_EVENTS 10
17 #define PORT 8080
19 //设置socket连接为非阻塞模式
20 void setnonblocking(int sockfd) {
21 int opts;
23 opts = fcntl(sockfd, F_GETFL);
24 if(opts < 0) {
25 perror("fcntl(F_GETFL)\n");
26 exit(1);
28 opts = (opts | O_NONBLOCK);
29 if(fcntl(sockfd, F_SETFL, opts) < 0) {
30 perror("fcntl(F_SETFL)\n");
31 exit(1);
35 int main(){
36 //ET模式的简单HTTP服务器代码
38 struct epoll_event ev, events[MAX_EVENTS];
39 int addrlen, listenfd, conn_sock, nfds, epfd, fd, i, nread, n;
40 struct sockaddr_in local, remote;
41 char buf[BUFSIZ];
43 //创建listen socket
44 if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
45 perror("sockfd\n");
46 exit(1);
48 setnonblocking(listenfd);
49 bzero(&local, sizeof(local));
50 local.sin_family = AF_INET;
51 local.sin_addr.s_addr = htonl(INADDR_ANY);;
52 local.sin_port = htons(PORT);
53 if( bind(listenfd, (struct sockaddr *) &local, sizeof(local)) < 0) {
54 perror("bind\n");
55 exit(1);
57 listen(listenfd, 20);
59 epfd = epoll_create(MAX_EVENTS);
60 if (epfd == -1) {
61 perror("epoll_create");
62 exit(EXIT_FAILURE);
65 ev.events = EPOLLIN;
66 ev.data.fd = listenfd;
67 if (epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev) == -1) {
68 perror("epoll_ctl: listen_sock");
69 exit(EXIT_FAILURE);
72 for (;;) {
73 nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
74 if (nfds == -1) {
75 perror("epoll_pwait");
76 exit(EXIT_FAILURE);
79 for (i = 0; i < nfds; ++i) {
80 fd = events[i].data.fd;
81 if (fd == listenfd) {
82 // ET下,正确的accept
83 while ((conn_sock = accept(listenfd,(struct sockaddr *) &remote,
84 (size_t *)&addrlen)) > 0) {
85 setnonblocking(conn_sock);
86 ev.events = EPOLLIN | EPOLLET;
87 ev.data.fd = conn_sock;
88 if (epoll_ctl(epfd, EPOLL_CTL_ADD, conn_sock,
89 &ev) == -1) {
90 perror("epoll_ctl: add");
91 exit(EXIT_FAILURE);
94 if (conn_sock == -1) {
95 if (errno != EAGAIN && errno != ECONNABORTED
96 && errno != EPROTO && errno != EINTR)
97 perror("accept");
99 continue;
101 if (events[i].events & EPOLLIN) {
102 // ET下,正确的读
103 n = 0;
104 while ((nread = read(fd, buf + n, BUFSIZ-1)) > 0) {
105 n += nread;
107 if (nread == -1 && errno != EAGAIN) {
108 perror("read error");
110 ev.data.fd = fd;
111 ev.events = events[i].events | EPOLLOUT;
112 if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) {
113 perror("epoll_ctl: mod");
116 if (events[i].events & EPOLLOUT) {
117 // ET下,正确的写
118 sprintf(buf, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\nHello World", 11);
119 int nwrite, data_size = strlen(buf);
120 n = data_size;
121 while (n > 0) {
122 nwrite = write(fd, buf + data_size - n, n);
123 if (nwrite < n) {
124 if (nwrite == -1 && errno != EAGAIN) {
125 perror("write error");
127 break;
129 n -= nwrite;
131 close(fd);
136 return 0;