首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

linux底上epoll模型服务端写数据到客户端

2012-10-21 
linux底下epoll模型服务端写数据到客户端?C/C++ code#include iostream#include sys/epoll.h#include

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_NONBLOCK);                                 //注册client                                                                ev.data.fd = clientFd;                                ev.events = EPOLLIN | EPOLLET|EPOLLOUT;                                epoll_ctl(epfd, EPOLL_CTL_ADD, clientFd, &ev);                                printf("one connect is accepted, %s\n", inet_ntoa(clientAddr.sin_addr));                                clientArry[i] = clientFd; //保存客户端套接字                                        }                    }                  else if(events[i].events&EPOLLIN)//读取数据                {                                        clientFd = events[i].data.fd;                    if(clientFd == -1)                    {                            continue;                    }                     while (true)                    {                        rlt = read(clientFd, acReadBuf, sizeof(acReadBuf));                        if(rlt < 0) //客户端异常断开                        {                            if(errno == EAGAIN)  //无数据,但连接存在                            {                                break;                            }                            else                             {                                printf("%d  clientFd close\n", clientFd);                                break;                            }                        }                        else if(rlt == 0) //客户端正常断开                        {                            close(clientFd);                            printf("%d  clientFd close\n", clientFd);                            ev = events[i];                            epoll_ctl(epfd, EPOLL_CTL_DEL, clientFd, &ev);                            break;                        }                        else                         {                            printf("clientFd  %d:\t%s\n ", clientFd, acReadBuf);                            memset(&acReadBuf, 0x00, sizeof(acReadBuf));                        }                                             }                }                                else if(events[i].events&EPOLLOUT)                {                    clientFd = events[i].data.fd;                    if(clientFd == -1)                    {                        continue;                    }                    while (true)                    {                        rlt = read(0, acWriteBuf, sizeof(acWriteBuf));                        if(rlt == -1)                        {                            perror("read error!\n");                            continue;                            }                                                rlt = write(events[i].data.fd, acWriteBuf, sizeof(acWriteBuf));                        if(rlt == -1)                        {                            perror("write error!\n");                            continue;                            }                                printf("write succese!\n");                                                                     }                }                            }        }        //关闭    }        close(listenFd);        close(epfd);} 



程序代码如上,如何实现能让服务端循环的写入数据到所有客户端,我现在的程序,虽然可以从服务端循环的写入数据到客户端,但是程序死在写入数据的循环中了,出不来,服务端从客户端读取的数据无法到屏幕显示,求教如何能使服务端和客户端之间循环的读取和写入数据。

[解决办法]
你这行有没有逻辑错误:
clientArry[i] = clientFd; //保存客户端套接字

另外,你自己写了个死循环不停的写,有什么办法呢!你每次只写一条数据啊,因为你外面的大循环是一起在循环的,所以还是等于不停的读写,只是读写交错一下。
[解决办法]
读写是个死循环,就有问题了。

应该在 events[i].events&EPOLLIN 下面读,
在 events[i].events&EPOLLOUT 下面写,
而后 
ev.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd, EPOLL_CTL_MOD, clientFd, &ev) 重置事件为继续读数据,重复上面的过程

热点排行