日期:2014-05-16  浏览次数:20607 次

linux底下epoll模型服务端写数据到客户端?
C/C++ code
#include <iostream>
#include <sys/epoll.h>
#include <time.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
using namespace std;

#define MAX_CONNECTED_NO 6
#define BUF_SIZE 512
#define LISTEN_PORT 10000
#define LOCAL_IP 127.0.0.1
#define MAX_EVENTS 5
#define ERR_EXIT(m) do \
{ \
    perror(m); \
    exit(EXIT_FAILURE); \
} while(0)

int main()
{
    int clientArry[20];
    for (int i = 0; i < 20; i++)
    {
        clientArry[i] = -1;    
    }
    char acReadBuf[BUF_SIZE] = {0};
    char acWriteBuf[BUF_SIZE] = {0};
    int listenFd = socket(AF_INET, SOCK_STREAM, 0);
    if(listenFd == -1)
    {
        ERR_EXIT("创建监听端口失败!\n");
    }
    
    int clientFd = -1;
    struct sockaddr_in serverAddr;
    memset(&serverAddr, 0x00, sizeof(struct sockaddr_in));
    
    struct sockaddr_in clientAddr;
    memset(&clientAddr, 0x00, sizeof(struct sockaddr_in));
    
    socklen_t addrlen;

    //初始化服务端套接字结构体
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(LISTEN_PORT);
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    //设置端口复用
    int yes = 1;
    int rlt = setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
    if(rlt == -1)
    {
        ERR_EXIT("设置端口复用失败!\n");
    }    
    
    //1.2非阻塞模式
    int flags = fcntl(listenFd, F_GETFL);
    fcntl(listenFd, F_SETFL, flags| O_NONBLOCK);
        
    //绑定
    rlt = bind(listenFd, (struct sockaddr *)(&serverAddr), sizeof(struct sockaddr_in));
    if(rlt == -1)
    {
        ERR_EXIT("绑定失败!\n");
    }

    //监听
    rlt = listen(listenFd, 5);
    if(rlt == -1)
    {
        ERR_EXIT("监听失败!\n");
    }

    //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
    struct epoll_event  ev;
    struct epoll_event   events[20];
    //生成用于处理accept的epoll专用的文件描述符
    int epfd=epoll_create(256);
    
    //注册监听的事件
    ev.data.fd = listenFd;
     ev.events=EPOLLIN|EPOLLET|EPOLLOUT;
    
    rlt = epoll_ctl(epfd, EPOLL_CTL_ADD, listenFd, &ev);
    if(rlt == -1)
    {
        ERR_EXIT("注册事件失败!\n");
        
    }
    struct timeval outtime;
    memset(&outtime, 0x00, sizeof(struct timeval));
    
    while(true)
    {
        outtime.tv_sec = 10;
        outtime.tv_usec = 0;
        //等待事件发生
        int nfds = epoll_wait(epfd, events, MAX_EVENTS,-1);
        if(nfds == -1)
        {
            perror("wait error!\n");
            continue;
        }            
        else if(nfds == 0)
        {
            printf("outtime .. \n");
            continue;
        }
        else 
        {
            for (int i = 0; i < nfds; i++)
            {
                if(events[i].data.fd == listenFd) //监听端口事件触发
                {
                        memset(&clientAddr, 0x00, sizeof(struct sockaddr_in));
                        clientFd = accept(listenFd, (struct sockaddr*)(&clientAddr), &addrlen);
                        if(clientFd == -1)
                        {
                                perror("accept error!\n");
                                continue;
                        }
                        else    
                        {
                                //设置client为非阻塞
                                int flags = fcntl(clientFd, F_GETFL);
                                fcntl(clientFd, F_SETFL, flags| O_NONBLO