C++ 技术中心

   :: 首页 :: 联系 ::  :: 管理
  160 Posts :: 0 Stories :: 87 Comments :: 0 Trackbacks

公告

郑重声明:本BLOG所发表的原创文章,作者保留一切权利。必须经过作者本人同意后方可转载,并注名作者(天空)和出处(CppBlog.com)。作者Email:coder@luckcoder.com

留言簿(27)

搜索

  •  

最新随笔

最新评论

评论排行榜

#include <sys/epoll.h>
#include 
<unistd.h>
//#include <linux/tcp.h>
#include <netinet/tcp.h>
#include 
<sys/types.h>
#include 
<sys/socket.h>
#include 
<unistd.h>
#include 
<fcntl.h>
#include 
<errno.h>
#include 
<string.h>
#include 
<arpa/inet.h>
#include 
<stdio.h>
#include 
<vector>
#include 
"../../Common/TypeDefine.h"
#include 
"../../Common/MemPool.h"


int32 set_nonblocking(
int fd)
{
    int32 oflags;
    
if ((oflags = fcntl(fd, F_GETFL, 0)) == -1)
        
return errno;
       
    
if (fcntl(fd, F_SETFL, oflags | O_NONBLOCK) == -1)
        
return errno;
    
return 0;
}




int32 epollDel(
int epfd,struct epoll_event *pEpev)
{
     
return epoll_ctl(epfd, EPOLL_CTL_DEL,pEpev->data.fd, pEpev);
}


int32 main(
int argc,char *argv[])
{    
    
//创建套接字
    int32 listenfd = socket(AF_INET,SOCK_STREAM,0);
    
if(listenfd < 0)
        
return -1;
    
    
//将套接字设为异步
    int32 ret= set_nonblocking(listenfd);
    
if(ret != 0)
        
return -1;
  
    int32 flag 
= 1;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, 
&flag, sizeof(flag)); //设置地址端口复用,服务器快速重起
    
    
// 设置SO_LINGER选项(防范CLOSE_WAIT挂住所有套接字)
    struct linger optval1;
    optval1.l_onoff 
= 1;
  optval1.l_linger 
= 60;
  setsockopt(listenfd, SOL_SOCKET, SO_LINGER, 
&optval1, sizeof(struct linger));
  
    
//创建epoll
    int32 maxSize = getdtablesize();  //返回某个进程所能打开的最大的文件数
    int32 epfd = epoll_create(maxSize);//创建一个epoll的句柄
    
    
if(epfd==-1)
        
return -1;
    printf(
"create epoll,maxSize=%d\n",maxSize);
    
    
//事件注册
    struct epoll_event epev;
  epev.events 
= EPOLLIN| EPOLLET;
  epev.data.fd 
= listenfd;
  
  int32 err 
= epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &epev);
  
  printf(
"register epoll event finish!\n");
    
    
//绑定端口
    printf("start bind,port=%d\n",9300);
    
struct sockaddr_in saddr;
    memset(
&saddr,0,sizeof(struct sockaddr_in));
    saddr.sin_family 
= AF_INET;
    saddr.sin_port 
= htons(9300);
    saddr.sin_addr.s_addr 
= inet_addr("127.0.0.1");
    
    ret 
= bind(listenfd,(struct sockaddr *)&saddr,sizeof(struct sockaddr_in));
  
if(ret < 0)
    
{
        
return -1;
    }


    ret 
= listen(listenfd,500);

    printf(
"listen finish!\n");
    

  
  
//循环
  int32 nev, i, millisecs = 200;
  
struct epoll_event m_evs[100];
  CHAR buf[
4096];
  
  
while(1)
  
{
             
if ((nev = epoll_wait(epfd, m_evs, 100, millisecs)) < 0)
                
{
                
if (errno == EINTR)
                    
continue;
                
else
                    
return -1;
            }

                   
          
for (i = 0; i < nev; i++{
              
                  printf(
"epoll wait event count=%d\n",nev);
                  
                           
if (m_evs[i].data.fd == listenfd)
                           
{
                                  
struct sockaddr_in addr;
                                  socklen_t len 
= sizeof(addr);
                                  int32 connfd 
= accept(listenfd,(struct sockaddr *)&addr, &len);
                                  
                                  printf(
"accept client fd=%d\n",connfd);
                                  
                                  
if (connfd < 0
                                  
{
                                            
if (errno == EWOULDBLOCK || errno == ECONNABORTED)
                                            
{
                                                printf(
"Failed to accept new connection (%s).\n", strerror(errno));
                                            
continue;
                                        }

                                            
else
                                                    
{
                                                        
//error
                                                        printf("Failed to accept new connection (%s).\n", strerror(errno));   
                                                        
continue;
                                                    }

                                            }

                                        
                                        
//将套接字设为异步
                                             if (set_nonblocking(connfd) != 0{
                                                close(connfd);
                                            
return -1;
                                        }

                                            
                                            int32 on
=1;
                                        setsockopt(connfd, IPPROTO_TCP, TCP_NODELAY,(
void *)&on,(socklen_t)sizeof(on));
                                        
                            
struct sockaddr_in clientaddr;
                            CHAR 
*str = inet_ntoa(clientaddr.sin_addr);
                            printf(
"accapt a connection from %s\n",str);
                            
                            
//设置用于读操作的文件描述符
                            struct epoll_event ev;
                            ev.data.fd
=connfd;
                            
//设置用于注测的读操作事件
                            ev.events=EPOLLIN|EPOLLET;
                            
//ev.data.ptr = new int8[4097];
                                            
                            
//注册ev
                            epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
                            
                            printf(
"accept client register epoll event!\n");
                           }

                           
else if(m_evs[i].events&EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入
                           {
                               printf(
"EVENT->EPOLLIN\n");
                               
                               
//先屏掉测试
                               
//continue;
                               
                               
//如果套接字错误
                               int32 sockfd;
                               
if ( (sockfd = m_evs[i].data.fd) < 0)
                               
{
                                     printf(
"error socket!\n");
                            
continue;
                        }

                                    
                                  int32 rv 
= 0;
                                  BOOL bClose 
= FALSE;
                                  int32 totalRv 
= 0;
                                  
char buf[4097={0};
                                  
const int32 maxRead = 10;
                                  
                                  rv 
= read(m_evs[i].data.fd,buf+totalRv,maxRead-totalRv);
                                    
while((rv > 0|| (rv < 0 && errno == EINTR))
                                    
{
                                          
if(rv>0)
                                            
{
                                                    totalRv 
+= rv;
                                                  printf(
"read context=[%s]\n",buf);
                                            }

                                            printf(
"read current size = %d,total size=%d\n",rv,totalRv);
                                            
                                          
                                          
//缓冲区读满 
                                          if(totalRv >= maxRead)
                                            
{
                                                    
break;
                                            }

                                            
                                            rv 
= read(m_evs[i].data.fd,buf+totalRv,maxRead-totalRv);
                                  }

                                  
                                  
//对端连接关闭
                                  
//EAGAIN没数据,EINTR被中断
                                  if(rv == 0 ||
                                      (rv 
< 0 && errno != EAGAIN && errno!=EINTR) )
                                  
{
                                         printf(
"read fail ,socket will close!\n");
                                         epollDel(epfd,
&m_evs[i]);
                                          close(m_evs[i].data.fd);
                             m_evs[i].data.fd 
= -1;
                             bClose 
= TRUE;
                                  }

                                  
else
                                  
{
                                       
//往对端发送写入数据事件
                                        struct epoll_event ev;
                            ev.data.fd
=m_evs[i].data.fd;
                            
//设置用于注测的读操作事件
                            
//ev.events=EPOLLIN|EPOLLOUT|EPOLLET;
                                            ev.events = m_evs[i].events | EPOLLOUT|EPOLLET;
                                            
                            
//将事件改为写
                            int32 ret = epoll_ctl(epfd,EPOLL_CTL_MOD,ev.data.fd,&ev);
                            printf(
"end add event ret = %d\n",ret);
                            
                            
if(ret == -1)
                            
{
                                  printf(
"Failed to accept new connection (%s),errno=%d.\n", strerror(errno),errno);
                            }

                                  }

                      }

                      
else if(m_evs[i].events&EPOLLOUT)
                      
{
                                    printf(
"EVENT->EPOLLOUT\n");
                                    
                                    
//先不写数据
                                    
//continue;
                                    
                                    
                                    int32 sockfd 
= m_evs[i].data.fd;
                                    
                                    
char buffer[4096]={0};
                                    
                                    CString str ;
                                    
                                    
for(int j=0;j<1;j++)
                                    
{
                                        str 
+= "0123456789";
                                    }

                                    
                                    strncpy(buffer,str.c_str(),
4095);
                                    
char *strPos = buffer;
                                    
int pos = 0;
                                    
int len = strlen(buffer);
                                    
                                    
int rv = write(sockfd,buffer+pos,len-pos);
                                            
while((rv >= 0|| (rv < 0 && errno == EINTR))
                                            
{
                                                  printf(
"write current size = %d,total size = %d\n",rv,pos);
                                                    
if(rv > 0)
                                                    
{
                                                         printf(
"write data size=%d\n",rv);
                                                    }

                                                
                                                  
//数据写完跳出
                                                    if(pos+1==len)
                                                        
break;
                                                    
                                                    
                                                    
if(rv>0)
                                                      pos 
+= rv;
                                                    
                                                
if(len - pos <=0)
                                                
{
                                                    printf(
"send data finish! size = %d\n",len);
                                                    
break;
                                                }

                                                    rv 
= write(sockfd,buffer+pos,len-pos);
                                            }

                                            
                                            
if(rv < 0 && errno != EAGAIN && errno != EINTR)
                                            
{
                                                  printf(
"write fail ,socket will close!\n");
                                                epollDel(epfd,
&m_evs[i]);
                                                   close(m_evs[i].data.fd);
                                      m_evs[i].data.fd 
= -1;
                                            }

                      }

                      
else if (m_evs[i].events&EPOLLERR || m_evs[i].events&EPOLLHUP)
                      
{
                            printf(
"events error ,socket will close!\n");
                                        epollDel(epfd,
&m_evs[i]);
                                        close(m_evs[i].data.fd);
                                m_evs[i].data.fd 
= -1;
                      }

                  }

   }


}
posted on 2013-08-09 10:30 C++技术中心 阅读(1710) 评论(0)  编辑 收藏 引用 所属分类: Linux 编程

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理