高性能服务器(epoll exsample code)

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/resource.h>




#define MAXBUF 16
#define MAXEPOLLSIZE 10000


/*
setnonblocking - 设置句柄为非阻塞方式
*/
int
setnonblocking (int sockfd)
{
if (fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFD, 0) | O_NONBLOCK) ==
-1)
{
return -1;
}
return 0;
}


/*
handle_message - 处理每个 socket 上的消息收发
*/
int
handle_message (int new_fd)
{
char buf[MAXBUF + 1];


int len, total = 0;


int rs = 1;


while (rs)
{
/* 开始处理每个新连接上的数据收发 */
bzero (buf, MAXBUF + 1);
/* 接收客户端的消息 */
len = recv (new_fd, buf, MAXBUF, 0);
if (len < 0)
{
if (errno == EAGAIN)
break;
else
{
printf ("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror (errno));
close (new_fd);
return -1;
}
}
else if (len == 0)
{
printf ("%d关闭\n", new_fd);
bzero (buf, MAXBUF + 1);
sprintf (buf, "%d个字节\n", total);
send(new_fd, buf, MAXBUF, 0);
close (new_fd);
return 0;
}
else
{
total += len;
printf ("%d接收消息成功:'%s',共%d个字节的数据\n", new_fd, buf, len);
if (len == MAXBUF)
rs = 1;
else
rs = 0;
}
}




/* 处理每个新连接上的数据收发结束 */
return len;
}


/************关于本文档********************************************
*filename: epoll-server.c
*purpose: 演示epoll处理海量socket连接的方法
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-31 21:00
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to:Google
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int
main (int argc, char **argv)
{
int listener, new_fd, kdpfd, nfds, n, ret, curfds;


socklen_t len;


struct sockaddr_in my_addr, their_addr;


unsigned int myport, lisnum;


struct epoll_event ev;


struct epoll_event events[MAXEPOLLSIZE];


struct rlimit rt;


if (argv[1])
myport = atoi (argv[1]);
else
myport = 7838;


if (argv[2])
lisnum = atoi (argv[2]);
else
lisnum = 2;


/* 设置每个进程允许打开的最大文件数 */
rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
if (setrlimit (RLIMIT_NOFILE, &rt) == -1)
{
perror ("setrlimit");
exit (1);
}
else
printf ("设置系统资源参数成功!\n");


/* 开启 socket 监听 */
if ((listener = socket (PF_INET, SOCK_STREAM, 0)) == -1)
{
perror ("socket");
exit (1);
}
else
printf ("socket 创建成功!\n");


setnonblocking (listener);


int on = 1;
ret = setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));


bzero (&my_addr, sizeof (my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons (myport);
if (argv[3])
my_addr.sin_addr.s_addr = inet_addr (argv[3]);
else
my_addr.sin_addr.s_addr = INADDR_ANY;


if (bind
(listener, (struct sockaddr *) &my_addr, sizeof (struct sockaddr))
== -1)
{
perror ("bind");
exit (1);
}
else
printf ("IP 地址和端口绑定成功\n");


if (listen (listener, lisnum) == -1)
{
perror ("listen");
exit (1);
}
else
printf ("开启服务成功!\n");


/* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */
kdpfd = epoll_create (MAXEPOLLSIZE);
len = sizeof (struct sockaddr_in);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = listener;
if (epoll_ctl (kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0)
{
fprintf (stderr, "epoll set insertion error: fd=%d\n", listener);
return -1;
}
else
printf ("监听 socket 加入 epoll 成功!\n");
curfds = 1;
while (1)
{
/* 等待有事件发生 */
nfds = epoll_wait (kdpfd, events, curfds, -1);
if (nfds == -1)
{
perror ("epoll_wait");
break;
}
/* 处理所有事件 */
for (n = 0; n < nfds; ++n)
{
if (events[n].data.fd == listener)
{
new_fd = accept (listener, (struct sockaddr *) &their_addr,
&len);
if (new_fd < 0)
{
perror ("accept");
continue;
}
else
printf
("有连接来自于: %d:%d, 分配的 socket 为:%d\n",
inet_ntoa (their_addr.sin_addr),
ntohs (their_addr.sin_port), new_fd);


setnonblocking (new_fd);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = new_fd;
if (epoll_ctl (kdpfd, EPOLL_CTL_ADD, new_fd, &ev) < 0)
{
fprintf (stderr,
"把 socket '%d' 加入 epoll 失败!%s\n",
new_fd, strerror (errno));
return -1;
}
curfds++;
}
else
{
ret = handle_message (events[n].data.fd);
if (ret < 1 && errno != 11)
{
epoll_ctl (kdpfd, EPOLL_CTL_DEL, events[n].data.fd,
&ev);
curfds--;
}
}
}
}
close (listener);
return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值