epoll示例

书到用时方恨少,一切尽在不言中

#include <iostream>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

using namespace std;

#define MAXLINE 5
#define OPEN_MAX 100
#define LISTENQ 20
#define SERV_PORT 5000
#define INFTIM 1000

void setnonblocking(int sock)
{
    int opts;
    opts=fcntl(sock,F_GETFL);
    if(opts<0)
    {
        perror("fcntl(sock,GETFL)");
        return;
    }
    opts = opts|O_NONBLOCK;

    if(fcntl(sock,F_SETFL,opts)<0)
    {
        perror("fcntl(sock,SETFL,opts)");
        return;
    }
}

void CloseAndDisable(int sockid, epoll_event ee)
{
    close(sockid);
    ee.data.fd = -1;
}

ssize_t socket_send(int sockfd, const char* buffer, size_t buflen)
{
  ssize_t tmp;
  size_t total = buflen;
  const char *p = buffer;

  while(1)
  {
     tmp = send(sockfd, p, total, 0);
     if(tmp < 0)
     {
        if(errno == EINTR)
            return -1;

        if(errno == EAGAIN)
        {
           usleep(1000);
           continue;
        }
           return -1;
     }

     if((size_t)tmp == total)
         return buflen;
     total -= tmp;
     p += tmp;
   }
   return tmp;
}
int main()
{
    int i, maxi, listenfd, connfd, sockfd,epfd,nfds, portnumber;
    char line[MAXLINE*50];
    socklen_t clilen;
    portnumber = 5000;

    struct epoll_event ev,events[20];
    epfd=epoll_create(256);

    struct sockaddr_in clientaddr;
    struct sockaddr_in serveraddr;
    listenfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port=htons(portnumber);

    bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));
    listen(listenfd, LISTENQ);

    ev.data.fd=listenfd;
    ev.events=EPOLLIN|EPOLLET;

    epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);

    maxi = 0;

    int bOut = 0;
    for ( ; ; )
    {
        if (bOut == 1)
            break;
        nfds=epoll_wait(epfd,events,20,-1);
        //printf("wait %d returns\n",nfds);
        for(i=0;i<nfds;++i)
        {
            if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口
            {
                connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);
                if(connfd<0){
                    perror("connfd<0");
                    return (1);
                }

                char *str = inet_ntoa(clientaddr.sin_addr);
                cout << "accapt a connection from " << str << endl;
                setnonblocking(connfd);
                ev.data.fd=connfd;
                ev.events=EPOLLIN | EPOLLET;
                //注册ev
                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
            }
            else if(events[i].events & EPOLLIN)
            {
                cout << "EPOLLIN" << endl;
                if ( (sockfd = events[i].data.fd) < 0)
                    continue;

                cout << "START READ" << endl;
                char * head = line;
                int recvNum = 0;
                int count = 0;
                bool bReadOk = false;
                while(1)
                {
                    recvNum = recv(sockfd, head+count, MAXLINE-1, 0);
                    if(recvNum < 0)
                    {
                        if(errno == EAGAIN)
                        {//已没数据 不阻塞等待
                            bReadOk = true;
                            break;
                        }
                        else if (errno == ECONNRESET)
                        {
                                CloseAndDisable(sockfd, events[i]);
                                cout << "counterpart send out RST\n";
                                break;
                         }
                        else if (errno == EINTR)
                        {//有数据但未读到断了,所以要接着读
                            continue;
                        }
                        else
                        {
                            CloseAndDisable(sockfd, events[i]);
                            cout << "unrecovable error\n";
                            break;
                        }
                   }
                   else if( recvNum == 0)
                   {
                        CloseAndDisable(sockfd, events[i]);
                        cout << "counterpart has shut off\n";
                        break;
                   }

                   count += recvNum;
                   if ( recvNum == MAXLINE-1)
                   {
                   cout << "sleeping..."<<endl;
           sleep(5);
                       cout << "recvNum == MAXLINE-1\n"<<endl;
                       continue;
                   }
                   else // 0 < recvNum < MAXLINE-1
                   {
                       cout << "0 < recvNum < MAXLINE-1"<<endl;
                       bReadOk = true;
                       break; // 退出while(1),表示已经全部读完数据
                   }

                }

                if (bReadOk == true)
                {
                    line[count] = ‘\0‘;
                    cout << "we have read from the client : " << line;
                    ev.data.fd=sockfd;
                    ev.events = EPOLLOUT | EPOLLET;
                    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
                }
            }
            else if(events[i].events & EPOLLOUT) // 如果有数据发送
            {
                cout << "EPOLLOUT" << endl;
                const char str[] = "1234567890";
        //printf("%d\n",sizeof(str));
                memcpy(line, str, sizeof(str));
                //cout << line << endl;
        printf("d %d u %u lu %lu\n",i,i,i);
                sockfd = events[i].data.fd;
                int bWritten = 0;
                int writenLen = 0;
                int count = 0;
                char * head = line;
        bWritten=socket_send(sockfd,head,strlen(head));
                if (bWritten == strlen(head))
                {
                    ev.data.fd=sockfd;
                    ev.events=EPOLLIN | EPOLLET;
                    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
                }
            }
        }
    }
    return 0;
}
时间: 2024-10-10 04:43:22

epoll示例的相关文章

IO多路复用:select、poll、epoll示例

一.IO多路复用 所谓IO多路复用,就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. Linux支持IO多路复用的系统调用有select.poll.epoll,这些调用都是内核级别的.但select.poll.epoll本质上都是同步I/O,先是block住等待就绪的socket,再是block住将数据从内核拷贝到用户内存. 当然select.poll.epoll之间也是有区别的,如下表: \ select poll e

非阻塞socket调用connect, epoll和select检查连接情况示例

from http://www.cnblogs.com/yuxingfirst/archive/2013/03/08/2950281.html 我们知道,linux下socket编程有常见的几个系统调用: 对于服务器来说, 有socket(), bind(),listen(), accept(),read(),write() 对于客户端来说,有socket(),connect() 这里主要要讲的是客户端这边的connect函数. 对于客户端来说,需要打开一个套接字,然后与对端服务器连接,例如:

统一事件源epoll代码示例

可以将信号注册进pipe管道的写端,通过对读端的监听,来实现统一事件源. #include <sys/types.h> #include <sys/socket.h> #include <sys/epoll.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <signal.

socket编程以及select、epoll、poll示例详解

socket编程socket这个词可以表示很多概念,在TCP/IP协议中“IP地址 + TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP + 端口号”就称为socket.在TCP协议中,建立连接的两个进程各自有一个socket来标识,那么两个socket组成的socket pair就唯一标识一个连接. 预备知识 网络字节序:内存中多字节数据相对于内存地址有大端小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分.网络数据流同样有大端小端之分,所以发送主机通常将发送缓冲

多线程和epoll的结合运用示例

//epoll通过将服务socket if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0) 添加到epoll中//然后listener监听链接请求,每次监听到一个新的链接就添加到epoll中 epoll_ctl//如果不是新的链接那么直接创建一个子线程进行业务的处理 #include <stdio.h>#include <stdlib.h>#include <errno.h>#include <

epoll简介 与 UDP server的实现

Abstractepoll是Linux内核为处理大批量句柄而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率. 简介:epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为: 它会复用文件描述符集合来传递结果, 而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因:

0730------Linux网络编程----------服务器端模型(迭代,多进程,多线程,select,poll,epoll 等)

1.迭代服务器模型 1.1 迭代服务器是处理多个请求时一种最简单直接的思路,即使用while循环,它不具有并发能力,即必须一个一个的处理客户的请求. 1.2 程序示例. #include "def.h" int listenfd_init(); //返回一个处于监听状态的套接字描述符 void do_service(int peerfd); // 处理客户端的请求 int main(int argc, const char *argv[]) { if(signal(SIGPIPE, S

Python——在Python中如何使用Linux的epoll

在Python中如何使用Linux的epoll 目录 序言 阻塞socket编程示例 异步socket的好处以及Linux epoll 带epoll的异步socket编程示例 性能注意事项 源代码 序言 从2.6开始,Python包含了访问Linux epoll库的API.这篇文章用几个简单的python 3例子来展示下这个API.欢迎大家质疑和反馈. 阻塞socket编程示例 示例1用python3.0搭建了一个简单的服务:在8080端口监听HTTP请求,把它打印到控制台,并返回一个HTTP响

编写案例分别使用多进程、多路复用(select、epoll)实现tcp服务

-------------------------------多进程的tcp服务器-------------------------------通过为每个客户创建一个进程的方式,能够同时为多个客户进行服务器当客户不是特别多的时候,这种方式还行,如果有几百上千个,就不可取了,因为每次创建进程等过程需要好较大的资源 python代码案例: 1 #coding=utf-8 2 3 #引用对应的包 4 from socket import * 5 6 from multiprocessing impor