Linux 网络编程 epoll中的EPOLLIN EPOLLOUT如何触发

问题描述

Linux 网络编程 epoll中的EPOLLIN EPOLLOUT如何触发

代码很长只截取关键部分
//服务器端
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include"locker.h"
#include"threadpool.h"
#include"http_conn.h"
#include"http_conn.cpp"
extern void addfd(int epollfd,int fd,bool one_shot);
extern void removefd(int epollfd,int fd);
#define MAX_FD 65536
#define MAX_EVENT_NUMBER 10000
void addsig(int sig,void(handler)(int),bool restart=true)
{
struct sigaction sa;
memset(&sa,'',sizeof(sa));
sa.sa_handler=handler;
if(restart)
{
sa.sa_flags|=SA_RESTART;
}
sigfillset(&sa.sa_mask);
assert(sigaction(sig,&sa,NULL)!=-1);
}

void show_error(int connfd,const char* info)
{
printf("%s",info);
send(connfd,info,strlen(info),0);
close(connfd);
}
int main(int argc,char* argv[])
{
if(argc
{
printf("usage: %s ip_address port_number
",basename(argv[0]));
return 1;
}
const char* ip=argv[1];
int port=atoi(argv[2]);
addsig(SIGPIPE,SIG_IGN);
threadpool* pool=NULL;

pool=new threadpool<http_conn>(3);

http_conn* users=new http_conn[MAX_FD];
assert(users);
int user_count=0;
int listenfd=socket(PF_INET,SOCK_STREAM,0);
assert(listenfd>=0);
struct linger tmp={1,0};
setsockopt(listenfd,SOL_SOCKET,SO_LINGER,&tmp,sizeof(tmp));

int ret=0;
struct sockaddr_in address;
bzero(&address,sizeof(address));
address.sin_family=AF_INET;
inet_pton(AF_INET,ip,&address.sin_addr);
address.sin_port=htons(port);

ret=bind(listenfd,(struct sockaddr*)&address,sizeof(address));
assert(ret>=0);

ret=listen(listenfd,5);
assert(ret>=0);

epoll_event events[MAX_EVENT_NUMBER];
int epollfd=epoll_create(5);
assert(epollfd!=-1);
addfd(epollfd,listenfd,false);
http_conn::m_epollfd=epollfd;
while(1)
{
    int number=epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1);
    printf("number is %d
",number);
    if((number<0)&&(errno!=EINTR))
    {
        printf("epoll failure
");
        break;
    }
    for(int i=0;i<number;i++)
    {
        int sockfd=events[i].data.fd;
        if(sockfd==listenfd)
        {
            struct sockaddr_in client_address;
            socklen_t client_addrlength=sizeof(client_address);
            int connfd=accept(listenfd,(struct sockaddr*)&client_address,&client_addrlength);
            if(connfd<0)
            {
                printf("errno is: %d
",errno);
                continue;
            }
            if(http_conn::m_user_count>=MAX_FD)
            {
                show_error(connfd,"Internal sever busy");
                continue;
            }
            printf("running the init(connfd,client_address)"
);
            users[connfd].init(connfd,client_address);

        }
        else if(events[i].events&(EPOLLRDHUP|EPOLLHUP|EPOLLERR))
        {
            users[sockfd].close_conn();
        }
        else if(events[i].events&EPOLLIN)
        {
            if(users[sockfd].read())
            {
                pool->append(users+sockfd);
            }
            else
            {
                users[sockfd].close_conn();
            }
        }
        else if(events[i].events&EPOLLOUT)
        {
            if(!users[sockfd].write())
            {
                users[sockfd].close_conn();
            }
        }
    }
}
close(epollfd);
close(listenfd);
delete [] users;
delete pool;
return 0;

}

以上是服务器端的主程序 思路是epoll_wait接收到连接就为连接创建一个users存储然后等待后续的操作 但后面EPOLLIN 和EPOLLOUT永远都没法触发 不清楚该怎么触发 另一端写了服务器压力测试程序 和以上代码类似 就是循环创建socket对象然后connect()服务器 但我本意想两端互相发送数据 可connect()后服务器收到创建一个user 继续循环等待 但压力测试程序也在创建完对象后陷入循环等待服务器端的操作 请问该如何触发EPOLLIN和EPOLLOUT信号

以下是压力测试程序关键代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static const char* request = "GET http://localhost/index.html HTTP/1.1
Connection: keep-alive

xxxxxxxxxx";
int setnonblocking(int fd)
{
int old_option=fcntl(fd,F_GETFL);
int new_option=old_option|O_NONBLOCK;
fcntl(fd,F_SETFL,new_option);
return old_option;
}
void addfd(int epollfd,int fd)
{
epoll_event event;
event.data.fd=fd;
event.events=EPOLLIN|EPOLLET|EPOLLRDHUP;
epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);
setnonblocking(fd);
}

bool write_nbytes(int sockfd,const char* buffer,int len)
{
int byters_write=0;
printf("write out %d bytes to socket %d
",len,sockfd);
while(1)
{
bytes_write=send(sockfd,buffer,len,0);
if(bytes_write==-1)
{
return false;
}
else if(bytes_write==0)
{
return false;
}
len-=bytes_write;
buffer=buffer+bytes_write;
if(len<=0)
{
return true;
}
}
}

bool read_once(int sockfd,char* buffer,int len)
{
int bytes_read=0;
memset(buffer,'',len);
bytes_read=recv(sockfd,buffer,len,0);
if(bytes_read==-1)
{
return false;
}
else if(bytes_read==0)
{
return false;
}
printf("read in %d bytes from socket %d with content: %s
",bytes_read,sockfd,buffer);
return true;
}
void start_conn(int epoll_fd,int num,const char* ip,int port)
{
int ret=0;
struct sockaddr_in address;
bzero(&address,sizeof(address));
address.sin_family=AF_INET;
inet_pton(AF_INET,ip,&address.sin_addr);
address.sin_port=htons(port);

for(int i=0;i<num;++i)
{
    sllep(1);
    int sockfd=socket(PF_INET,SOCK_STREAM,0);
    printf("create 1 sock
");
    if(sockfd<0)
    {
        continue;
    }
    if(connect(sockfd,(struct sockaddr*)&address,sizeof(address))==0)
    {
        printf("build connection %d
",i);
        addfd(epoll_fd,sockfd);
    }
}

}
void close_conn(int epoll_fd,int sockfd)
{
epoll_ctl(epoll_fd,EPOLL_CTL_DEL,sockfd,0);
close(sockfd);
}

int main(int argc,char* argv[])
{
assert(argc==4);
int epoll_fd=epoll_create(100);
start_conn(epoll_fd,atoi(argv[3]),argv[1],atoi(argv[2]));
epoll_event events[10000];
char buffer[2048];

while(1)
{
    int fds=epoll_wait(epoll_fd,events,10000,2000);
    for(int i=0;i<fds;i++)
    {
        int sockfd=events[i].data.fd;
        if(event[i].events&EPOLLIN)
        {
            if(!read_once(sockfd,buffer,2048));
            {
                close_conn(epoll_fd,sockfd);
            }
            struct epoll_event event;
            event.events=EPOLLOUT|EPOLLET|EPOLLERR;
            event.data.fd=sockfd;
            epoll_ctl(epoll_fd,EPOLL_CTL_MOD,sockfd,&event);
        }
        else if(events[i].events&EPOLLOUT)
        {
            if(!write_nbytes(sockfd,request,strlen(request)))
            {
                close_conn(epoll_fd,sockfd);
            }
            struct epoll_event event;
            event.events=EPOLLIN|EPOLLET|EPOLLERR;
            event.data.fd=sockfd;
            epoll_ctl(epoll_fd,EPOLL_CTL_MOD,sockfd,&event);
        }
        else if(events[i].events&EPOLLERR)
        {
            close_conn(epoll_fd,sockfd);
        }
    }
}

}

解决方案

linux 网络编程 epoll
linux网络编程之 epoll
Linux网络编程之epoll

解决方案二:

你的得先注册事件监听啊。把要监控的套接字和要监听的事件注册

时间: 2024-11-02 20:02:41

Linux 网络编程 epoll中的EPOLLIN EPOLLOUT如何触发的相关文章

Linux网络编程 epoll中EPOLLIN EPOLLOUT信号无法触发

问题描述 Linux网络编程 epoll中EPOLLIN EPOLLOUT信号无法触发 比如 if(events[i].events&EPOLLIN) { int bytes_read=read(m_sockfd,read_buf,READ_BUFFER_SIZE); } 这样会触发EPOLLIN 但如果把read()封装到比如service类的sread()函数中 if(events[i].events&EPOLLIN) { service.sread() } 便不会触发EPOLLIN事

linux网络编程epoll详解

在linux的网络编程中,很长的时间都在使用select来做事件触发.在linux新的内核中,有了一种替换它 的机制,就是epoll. 相比于select,epoll最大的好处在于它不会随着监听fd数目的增长而降低效率.因 为在内核中的select实现中,它是采用轮询来处理的,轮询的fd数目越多,自然耗时越多.并且,在 linux/posix_types.h头文件有这样的声明: #define __FD_SETSIZE    1024 表示select最 多同时监听1024个fd,当然,可以通过

处理Linux网络编程中的IP地址

 Linux网络服务能力非常强大,它的TCP/IP代码是最高级的.Linux的网络实现是模仿FreeBSD的,它支持FreeBSD的带有扩展的Sockets(套接字)和TCP/IP协议.它支持两个主机间的网络连接和Sockets通讯模型,实现了两种类型的Sockets:BSD Sockets和INET Sockets.它为不同的通信模型和服务质量提供了两种传输协议,即不可靠的.基于消息的UDP传输协议和可靠的.基于流的传输协议TCP,并且都是在IP网络协议上实现的.INET sockets是在以

Linux网络编程入门

(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍 客户端和服务端          网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端         在网络程序中,如果一个程序主动和外面的程序通信,那么我们把这个程序称为客户端程序. 比如我们使用ftp程序从另外一         个地方获取文件的时候,是我们的ftp程序主动同外面进行通信(获取文件), 所以这个地方我们的ftp程序就是客户端程序.  服务端        

Linux 网络编程 之 TCP状态转换

                                               Linux 网络编程 之 TCP状态装换                                                                       从上面的图中可以看出,TCP共有11状态.由TCP发送和接收的数据有:ACK, FIN, SYN,RST.对于一个还未调用connect的client和未调用listen的server来说,它们都处于CLOSED状态.ACK

Linux网络编程socket选项之SO_LINGER,SO_REUSEADDR

                       Linux网络编程socket选项之SO_LINGER,SO_REUSEADDR Linux网络编程中,socket的选项很多.其中几个比较重要的选项有:SO_LINGER(仅仅适用于TCP,SCTP), SO_REUSEADDR.   SO_LINGER 在默认情况下,当调用close关闭socke的使用,close会立即返回,但是,如果send buffer中还有数据,系统会试着先把send buffer中的数据发送出去,然后close才返回.

Linux网络编程一步一步学【转】

转自:http://blog.chinaunix.net/uid-10747583-id-297982.html Linux网络编程一步一步学+基础  原文地址:http://blogold.chinaunix.net/u1/48325/showart_413841.html ·Linux网络编程基础(一)·Linux网络编程基础(二)·Linux网络编程基础(三) • Linux网络编程一步一步学-简单客户端编写   • Linux网络编程一步一步学-绑定IP和端口 • Linux网络编程一步

Proxy源代码分析--谈谈如何学习linux网络编程

原创地址: http://fanqiang.chinaunix.net/a4/b7/20010810/1200001101.html   Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到,Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该是Windows的优点)相比,后者无疑在易操作性上更胜一筹.但是为什么又有那么多的爱好者钟情于Linux呢,当然自由是最吸引人的一点,另外Linux强大的功能也是一个非常重要

linux网络编程libpcap获取网络接口信息失败

问题描述 linux网络编程libpcap获取网络接口信息失败 #include typedef u_int32_t in_addr_t; struct in_addr{ in_addr_t s_addr;}; void main(){ char error_content[PCAP_ERRBUF_SIZE]; struct in_addr net_ip_address; struct in_addr net_mask_address; char *net_interface; char *ne