当前位置: 技术问答>linux和unix
一个简单的epoll程序使得客户端死循环了,为什么?
来源: 互联网 发布时间:2017-02-06
本文导语: 再开一贴: 我的一个小程序里面,父进程是服务器端,创建一个子进程当客户端。 服务器端每隔1s钟发送一个消息,子进程接受并打印出来。 但我运行的结果却是: Get EPOLLIN Get EPOLLIN Get EPOLLIN Get EPOLLIN...
再开一贴: 我的一个小程序里面,父进程是服务器端,创建一个子进程当客户端。
服务器端每隔1s钟发送一个消息,子进程接受并打印出来。
但我运行的结果却是:
Get EPOLLIN
Get EPOLLIN
Get EPOLLIN
Get EPOLLIN
Get EPOLLIN
Get EPOLLIN
Get EPOLLIN
不断打印。
代码的问题在哪儿? 我怀疑我epoll模型用的不对。网上说epoll_wait之后要重新epoll_ctl,这个是可选的还是必须做的?
服务器端每隔1s钟发送一个消息,子进程接受并打印出来。
但我运行的结果却是:
Get EPOLLIN
Get EPOLLIN
Get EPOLLIN
Get EPOLLIN
Get EPOLLIN
Get EPOLLIN
Get EPOLLIN
不断打印。
代码的问题在哪儿? 我怀疑我epoll模型用的不对。网上说epoll_wait之后要重新epoll_ctl,这个是可选的还是必须做的?
#include
#include
#include
#include
#include
#include
#include
#include
void server(void)
{
int sockSrv=socket(AF_INET,SOCK_STREAM,0);
if(sockSrv==-1)return;
sockaddr_in sAddr;
sAddr.sin_family=AF_INET;
sAddr.sin_port =htons(34567);
sAddr.sin_addr.s_addr =htonl(INADDR_ANY);
if(-1 == bind( sockSrv, (sockaddr*)&sAddr, sizeof( sockaddr )))return;
if(-1 == listen(sockSrv,0))return;
socklen_t cbAddr = sizeof(sockaddr);
while(1){
int iAccSock = accept(sockSrv, (sockaddr*)&sAddr, &cbAddr );
if(iAccSock==-1)return;
printf("Server: Accepted!n");
long i=0;
while(1){
char buf[6]={0};
sprintf(buf,"%d",++i);
if(-1 == send(iAccSock,buf,strlen(buf),0) ){
printf("Server: send errorn");
close(iAccSock);
break;
}
printf("Server: data sent=%sn",buf);
sleep(1);
}
close(iAccSock);
}
}
int createPoll(int hClient)
{
int fd_epoll = epoll_create(1);
if(fd_epoll==-1)
{
printf("epoll_create failedn");
return 0;
}
epoll_event ee;
ee.events=EPOLLIN;
int ret=epoll_ctl(fd_epoll,EPOLL_CTL_ADD,hClient,&ee);
if(ret==-1)
{
printf("epoll_ctl failedn");
return 0;
}
while(true)
{
int fd=epoll_wait(fd_epoll,&ee,1,-1);
if(fd=recv(hClient,buf,sizeof(buf),0)){
printf("Client: recv errorn");
break;
}
printf("Client: recv=%sn",buf);
}
}
}//end while
}
void client(void)
{
int hClient=socket(AF_INET,SOCK_STREAM,0);
if(hClient==-1)return;
sockaddr_in sAddr;
sAddr.sin_family=AF_INET;
sAddr.sin_port =htons(34567);
sAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
if( -1==connect( hClient, (sockaddr*)&sAddr, sizeof(sockaddr) ) )
{
printf("Client: Async connect errorn");
return;
}
printf("Client: Connectedn");
createPoll(hClient);
close(hClient);
return;
}
int main(void)
{
pid_t pid=fork();
if(pid==0)
{//child
sleep(1);
client();
}
else//father
{
server();
}
return 0;
}
|
我没玩过 epoll,刚才在网上学习了下,呵呵
epoll_event ee;
ee.data.fd=hClient;
ee.events=EPOLLIN;
int ret=epoll_ctl(fd_epoll,EPOLL_CTL_ADD,hClient,&ee);
在epoll_ctl之前,加那么一句看看
epoll_event ee;
ee.data.fd=hClient;
ee.events=EPOLLIN;
int ret=epoll_ctl(fd_epoll,EPOLL_CTL_ADD,hClient,&ee);
在epoll_ctl之前,加那么一句看看
|
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CONN_MAX 65536
#define EV_BUF_SIZE 1024
#define E_READ 0x01
#define E_WRITE 0x02
#define RS_BUFF_SIZE 8197
static int epollfd = 0;
static int max_connections = 0;
static int lfd = 0;
static struct sockaddr_in sa = {0};
static socklen_t sa_len = sizeof(struct sockaddr_in);
static int ev_sock_type = 0;
static int ev_sock_list[] = {SOCK_STREAM, SOCK_DGRAM};
static int ev_sock_count = 2;
static in_addr_t multicast_addr = INADDR_NONE;
typedef struct _CONN
{
int fd;
int x;
int nout;
int n;
int keepalive;
char out[EV_BUF_SIZE];
char buffer[EV_BUF_SIZE];
}CONN;
static CONN *conns = NULL;
static char *out_block = NULL;
static char out_data[EV_BUF_SIZE];
static int out_data_len = 0;
static char kout_data[EV_BUF_SIZE];
static int kout_data_len = 0;
/* set rlimit */
char* GetHtml(const char *pFileName)
{}
int setrlimiter(char *name, int rlimit, int nset)
{
int ret = -1;
struct rlimit rlim;
if(name)
{
if(getrlimit(rlimit, &rlim) == -1)
return -1;
else
{
fprintf(stdout, "getrlimit %s cur[%ld] max[%ld]n",
name, (long)rlim.rlim_cur, (long)rlim.rlim_max);
}
if(rlim.rlim_cur > nset && rlim.rlim_max > nset)
return 0;
rlim.rlim_cur = nset;
rlim.rlim_max = nset;
if((ret = setrlimit(rlimit, &rlim)) == 0)
{
fprintf(stdout, "1: setrlimit %s cur[%ld] max[%ld]n",
name, (long)rlim.rlim_cur, (long)rlim.rlim_max);
return 0;
}
else
{
fprintf(stderr, "2: setrlimit %s cur[%ld] max[%ld] failed, %sn",
name, (long)rlim.rlim_cur, (long)rlim.rlim_max, strerror(errno));
}
}
return ret;
}
void ev_handler(int fd, int ev_flags, void *arg)
{
int rfd = 0, n = 0, out_len = 0;
struct sockaddr_in rsa;
socklen_t rsa_len = sizeof(struct sockaddr_in);
struct epoll_event evp;
char *out = NULL;
if(fd == lfd )
{
if((ev_flags & E_READ))
{
while((rfd = accept(fd, (struct sockaddr *)&rsa, &rsa_len)) > 0)
{
conns[rfd].fd = rfd;
/* set FD NON-BLOCK */
conns[rfd].n = 0;
fcntl(rfd, F_SETFL, fcntl(rfd, F_GETFL, 0)|O_NONBLOCK);
memset(&evp, 0, sizeof(struct epoll_event));
evp.data.fd = rfd;
evp.events = EPOLLIN;
epoll_ctl(epollfd, EPOLL_CTL_ADD, evp.data.fd, &evp);
}
return ;
}
}
else
{
if(ev_flags & E_READ)
{
n = read(fd, conns[fd].buffer+conns[fd].n, EV_BUF_SIZE - conns[fd].n);
if(n > 0)
{
conns[fd].n += n;
conns[fd].buffer[conns[fd].n] = 0;
if(strstr(conns[fd].buffer, "rnrn"))
{
if(strcasestr(conns[fd].buffer, "Keep-Alive")) conns[fd].keepalive = 1;
conns[fd].x = 0;
conns[fd].n = 0;
memset(&evp, 0, sizeof(struct epoll_event));
evp.data.fd = fd;
evp.events = EPOLLOUT;
epoll_ctl(epollfd, EPOLL_CTL_MOD, evp.data.fd, &evp);
}
}
else
{
goto err;
}
}
if(ev_flags & E_WRITE)
{
if(conns[fd].keepalive){out = kout_data;out_len = kout_data_len;}
else {out = out_data; out_len = out_data_len;}
n = write(fd, out + conns[fd].x, out_len - conns[fd].x);
if(n > 0 )
{
conns[fd].x += n;
if(conns[fd].x 0) ? connection_limit : CONN_MAX;
/* Set resource limit */
setrlimiter("RLIMIT_NOFILE", RLIMIT_NOFILE, CONN_MAX);
out_block = GetHtml("./Template.html");
//printf("%srn", out_block);
out_data_len = sprintf(out_data, "HTTP/1.0 200 OKrnContent-Length: %drnrn%s", (int)strlen(out_block), out_block);
kout_data_len = sprintf(kout_data, "HTTP/1.0 200 OKrnConnection: Keep-AlivernContent-Length: %drnrn%s", (int)strlen(out_block), out_block);
/* Initialize global vars */
if((conns = (CONN *)calloc(CONN_MAX, sizeof(CONN))))
{
memset(&sa, 0, sizeof(struct sockaddr_in));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = htons(port);
sa_len = sizeof(struct sockaddr_in );
/* Initialize inet */
lfd = socket(AF_INET, ev_sock_list[ev_sock_type], 0);
if(setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR,
(char *)&opt, (socklen_t) sizeof(opt)) != 0
#ifdef SO_REUSEPORT
|| setsockopt(lfd, SOL_SOCKET, SO_REUSEPORT,
(char *)&opt, (socklen_t) sizeof(opt)) != 0
#endif
)
{
fprintf(stderr, "setsockopt[SO_REUSEADDR] on fd[%d] failed, %s", fd, strerror(errno));
_exit(-1);
}
/* Bind */
if(bind(lfd, (struct sockaddr *)&sa, sa_len) != 0 )
{
//SHOW_LOG("Binding failed, %s", strerror(errno));
return -1;
}
/* set FD NON-BLOCK */
if(fcntl(lfd, F_SETFL, fcntl(lfd, F_GETFL, 0)|O_NONBLOCK) != 0 )
{
//SHOW_LOG("Setting NON-BLOCK failed, %s", strerror(errno));
return -1;
}
/* Listen */
if(ev_sock_list[ev_sock_type] == SOCK_STREAM)
{
if(listen(lfd, CONN_MAX) != 0 )
{
//SHOW_LOG("Listening failed, %s", strerror(errno));
return -1;
}
}
/* set multicast */
if(ev_sock_list[ev_sock_type] == SOCK_DGRAM && multicast_ip)
{
struct ip_mreq mreq;
memset(&mreq, 0, sizeof(struct ip_mreq));
mreq.imr_multiaddr.s_addr = multicast_addr = inet_addr(multicast_ip);
mreq.imr_interface.s_addr = INADDR_ANY;
if(setsockopt(lfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char*)&mreq, sizeof(mreq)) != 0)
{
//SHOW_LOG("Setsockopt(MULTICAST) failed, %s", strerror(errno));
return -1;
}
}
//SHOW_LOG("Initialize evbase ");
struct epoll_event evp, events[CONN_MAX];
int flag = 0, n = 0;
if((epollfd = epoll_create(CONN_MAX)) > 0)
{
memset(&evp, 0, sizeof(struct epoll_event));
evp.data.fd = lfd;
evp.events = EPOLLIN|EPOLLET;
epoll_ctl(epollfd, EPOLL_CTL_ADD, lfd, &evp);
do
{
n = epoll_wait(epollfd, events, CONN_MAX, -1);
for(i = 0; i