epoll文件服务器,基于epoll实现的一个简单的web服务器

详解1

EPOLLIN:文件描述符可以读

EPOLLOUT:文件描述符可以写

EPOLLPRI:文件描述符有紧急的数据可写

EPOLLERR:文件描述符发生错误

EPOLLHUP:文件描述符被挂起

EPOLLET: 文件描述符有事件发生

所用到的函数:

1、int epoll_create(int size)

该函数生成一个epoll专用的文件描述符,其中的参数是指定生成描述符的最大范围(在我们做网络开发中应该是可以管理的端口的个数。就是可以接受链接的socket的个数)。

2、int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

该函数用于控制某个文件描述符上的事件,可以注册事件,修改事件,删除事件。

参数:epfd:由 epoll_create 生成的epoll专用的文件描述符;

op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修改、EPOLL_CTL_DEL 删除

fd:关联的socket文件描述符;

event:指向epoll_event的指针,根据op的值对fd管理的事件进行操作,更改的事件在event中存放;

如果调用成功返回0,不成功返回-1

3、int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)

该函数用于轮询I/O事件的发生;

参数:

epfd:由epoll_create 生成的epoll专用的文件描述符;

epoll_event:用于回传代处理事件的数组,即使将所有满足条件的socket文件描述对应的epoll_event中条件的epoll_event放到events数组中 ;

maxevents:每次能处理的事件数的最大值;

timeout:等待I/O事件发生的超时值;

返回发生事件数。

下面是一个例子:(本程序是在ubuntu12.04中运行成功,如果在别的系统上无法运行请谅解)

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

/*设这文件句柄sfd为非阻塞

*

*/

static int make_socket_non_blocking (int sfd)

{

int flags, s;

flags = fcntl (sfd, F_GETFL, 0);

if (flags == -1)

{

perror ("fcntl");

return -1;

}

flags |= O_NONBLOCK;

s = fcntl (sfd, F_SETFL, flags);

if (s == -1)

{

perror ("fcntl");

return -1;

}

return 0;

}

/*创建epoll管理最大文件句柄的个数

*parameter

* @maxfds:最大的句柄个数。也就是网站数目。端口的数目

*/

int epoll_init(int maxfds)

{

return epoll_create(maxfds);

}

/*设这epoll管理每个文件句柄的参数和方法

*parameter

* @fd:要管理socket文件句柄

* @maxfds:管理socket文件句柄的个数

*/

static struct epoll_event * epoll_event_init(int * fd, int maxfds)

{

struct epoll_event *events;

int i = 0;

if(0 >= maxfds || NULL ==fd) return NULL;

events = (struct epoll_event *)malloc( sizeof(struct epoll_event) * maxfds);

for(; i < maxfds; i++)

{

events[i].data.fd = fd[i];

events[i].events = EPOLLIN | EPOLLET;

}

return events;

}

int epoll_handler(int epfd, int * fd, int maxfds)

{

struct epoll_event *events = epoll_event_init(fd, maxfds);

struct epoll_event *ev = events;

int i = 0;

for(; i < maxfds; i++)

{

epoll_ctl(epfd, EPOLL_CTL_ADD, fd[i], ev);

ev++;

}

}

/*

@description:开始服务端监听

@parameter

ip:web服务器的地址

port:web服务器的端口

@result:成功返回创建socket套接字标识,错误返回-1

*/

int socket_listen( char *ip, unsigned short int port)

{

int res_socket; //返回值

int res, on;

struct sockaddr_in address;

struct in_addr in_ip;

res = res_socket = socket(AF_INET, SOCK_STREAM, 0);

setsockopt(res_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

memset(&address, 0, sizeof(address));

address.sin_family = AF_INET ;

address.sin_port =htons(port);

address.sin_addr.s_addr = htonl(INADDR_ANY); //inet_addr("127.0.0.1");

res = bind( res_socket, (struct sockaddr *) &address, sizeof( address ) );

if(res) { printf( "port is used , not to repeat bind\n" ); exit(101); };

res = listen(res_socket,5);

if(res) { printf( "listen port is error ;\n" ); exit( 102 ); };

return res_socket ;

}

void send_http1(int conn_socket)

{

char *send_buf = "HTTP/1.1 200 OK\r\nServer: Reage webserver\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n

epoll learn

Reage Test111111

Hello World! \r\n\r\n";

write(conn_socket, send_buf, strlen(send_buf));

}

void send_http2(int conn_socket)

{

char *send_buf = "HTTP/1.1 200 OK\r\nServer: Reage webserver\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n

epoll learn

Reage Test22222

Hello World! \r\n\r\n";

write(conn_socket, send_buf, strlen(send_buf));

}

int main(int argc, char * argv[] )

{

int res_socket[2];

struct epoll_event event[100];

struct sockaddr_in client_addr;

int len;

res_socket[0] = socket_listen( "127.0.0.1", 1025) ;

res_socket[1] = socket_listen( "127.0.0.1", 1024) ;

make_socket_non_blocking(res_socket[0]);

make_socket_non_blocking(res_socket[1]);

int epfd = epoll_init(2);

epoll_handler(epfd, res_socket, 2);

while(1)

{

int count = epoll_wait(epfd, event, 2, -1);

while(count--)

{

sleep(10);

int connfd = accept(event[count].data.fd, (struct sockaddr *)&client_addr, &len);

//针对不同的端口,即是不同的网站进行不同的处理

if( event[count].data.fd == res_socket[0])

send_http1(connfd);

else

send_http2(connfd);

close(connfd);

}

}

}

blogs

:http://blog.csdn.net/rentiansheng/article/details/8684194

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值