5 #include <sys/socket.h>
14 //功能:创建和绑定一个TCP socket
18 create_and_bind (char *port
)
20 struct addrinfo hints
;
21 struct addrinfo
*result
, *rp
;
24 memset (&hints
, 0, sizeof (struct addrinfo
));
25 hints
.ai_family
= AF_UNSPEC
; /* Return IPv4 and IPv6 choices */
26 hints
.ai_socktype
= SOCK_STREAM
; /* We want a TCP socket */
27 hints
.ai_flags
= AI_PASSIVE
; /* All interfaces */
29 s
= getaddrinfo (NULL
, port
, &hints
, &result
);
32 fprintf (stderr
, "getaddrinfo: %s\n", gai_strerror (s
));
36 for (rp
= result
; rp
!= NULL
; rp
= rp
->ai_next
)
38 sfd
= socket (rp
->ai_family
, rp
->ai_socktype
, rp
->ai_protocol
);
42 s
= bind (sfd
, rp
->ai_addr
, rp
->ai_addrlen
);
45 /* We managed to bind successfully! */
54 fprintf (stderr
, "Could not bind\n");
58 freeaddrinfo (result
);
67 make_socket_non_blocking (int sfd
)
72 flags
= fcntl (sfd
, F_GETFL
, 0);
81 s
= fcntl (sfd
, F_SETFL
, flags
);
93 main (int argc
, char *argv
[])
97 struct epoll_event event
;
98 struct epoll_event
*events
;
102 fprintf (stderr
, "Usage: %s [port]\n", argv
[0]);
106 sfd
= create_and_bind (argv
[1]);
110 s
= make_socket_non_blocking (sfd
);
114 s
= listen (sfd
, SOMAXCONN
);
121 //除了参数size被忽略外,此函数和epoll_create完全相同
122 efd
= epoll_create1 (0);
125 perror ("epoll_create");
130 event
.events
= EPOLLIN
| EPOLLET
;//读入,边缘触发方式
131 s
= epoll_ctl (efd
, EPOLL_CTL_ADD
, sfd
, &event
);
134 perror ("epoll_ctl");
138 /* Buffer where events are returned */
139 events
= calloc (MAXEVENTS
, sizeof event
);
146 n
= epoll_wait (efd
, events
, MAXEVENTS
, -1);
147 for (i
= 0; i
< n
; i
++)
149 if ((events
[i
].events
& EPOLLERR
) ||
150 (events
[i
].events
& EPOLLHUP
) ||
151 (!(events
[i
].events
& EPOLLIN
)))
153 /* An error has occured on this fd, or the socket is not
154 ready for reading (why were we notified then?) */
155 fprintf (stderr
, "epoll error\n");
156 close (events
[i
].data
.fd
);
160 else if (sfd
== events
[i
].data
.fd
)
162 /* We have a notification on the listening socket, which
163 means one or more incoming connections. */
166 struct sockaddr in_addr
;
169 char hbuf
[NI_MAXHOST
], sbuf
[NI_MAXSERV
];
171 in_len
= sizeof in_addr
;
172 infd
= accept (sfd
, &in_addr
, &in_len
);
175 if ((errno
== EAGAIN
) ||
176 (errno
== EWOULDBLOCK
))
178 /* We have processed all incoming
190 s
= getnameinfo (&in_addr
, in_len
,
193 NI_NUMERICHOST
| NI_NUMERICSERV
);//flag参数:以数字名返回
198 printf("Accepted connection on descriptor %d "
199 "(host=%s, port=%s)\n", infd
, hbuf
, sbuf
);
202 /* Make the incoming socket non-blocking and add it to the
203 list of fds to monitor. */
204 s
= make_socket_non_blocking (infd
);
208 event
.data
.fd
= infd
;
209 event
.events
= EPOLLIN
| EPOLLET
;
210 s
= epoll_ctl (efd
, EPOLL_CTL_ADD
, infd
, &event
);
213 perror ("epoll_ctl");
221 /* We have data on the fd waiting to be read. Read and
222 display it. We must read whatever data is available
223 completely, as we are running in edge-triggered mode
224 and won't get a notification again for the same
233 count
= read (events
[i
].data
.fd
, buf
, sizeof(buf
));
236 /* If errno == EAGAIN, that means we have read all
237 data. So go back to the main loop. */
247 /* End of file. The remote has closed the
253 /* Write the buffer to standard output */
254 s
= write (1, buf
, count
);
264 printf ("Closed connection on descriptor %d\n",
267 /* Closing the descriptor will make epoll remove it
268 from the set of descriptors which are monitored. */
269 close (events
[i
].data
.fd
);