这篇博客介绍使用epoll函数实现并发服务器。
服务端代码:
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/sendfile.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <errno.h>
#define MAX_EVENTS 10
#define LISTENQ 20
#define PORT 5000 //8080
//设置socket连接为非阻塞模式
void setnonblocking (int fd)
{
int opts;
opts = fcntl (fd, F_GETFL);
if (opts < 0)
{
perror ("fcntl(F_GETFL)\n");
exit (1);
}
opts = (opts | O_NONBLOCK);
if (fcntl (fd, F_SETFL, opts) < 0)
{
perror ("fcntl(F_SETFL)\n");
exit (1);
}
}
int main ()
{
struct epoll_event ev, events[MAX_EVENTS];
int listenfd, connfd, nfds, epfd, sockfd, i, nread, n;
struct sockaddr_in local, remote;
socklen_t addrlen;
char buf[BUFSIZ];
//创建listen socket
if ((listenfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
{
perror ("sockfd\n");
exit (1);
}
setnonblocking (listenfd);
bzero (&local, sizeof (local));
local.sin_family = AF_INET;
local.sin_addr.s_addr = htonl (INADDR_ANY);;
local.sin_port = htons (PORT);
if (bind (listenfd, (struct sockaddr *) &local, sizeof (local)) < 0)
{
perror ("bind\n");
exit (1);
}
listen (listenfd, LISTENQ);
epfd = epoll_create (MAX_EVENTS);
if (epfd == -1)
{
perror ("epoll_create");
exit (EXIT_FAILURE);
}
ev.events = EPOLLIN;
ev.data.fd = listenfd;
if (epoll_ctl (epfd, EPOLL_CTL_ADD, listenfd, &ev) == -1)
{
perror ("epoll_ctl: listen_sock");
exit (EXIT_FAILURE);
}
for (;;)
{
nfds = epoll_wait (epfd, events, MAX_EVENTS, -1);
if (nfds == -1)
{
perror ("epoll_wait error