读取事件从未触发,使用libevent



我只是使用libevent编写了一个echo服务器,但似乎从未触发读取事件。代码为:

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/tcp.h>
#include <event.h>
#include <event2/event.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
static short ListenPort = 19999;
static long ListenAddr = INADDR_ANY;//任意地址,值就是0
static int   MaxConnections = 1024;
static int ServerSocket;
static struct event ServerEvent;
int SetNonblock(int fd)
{
    int flags;
    if ((flags = fcntl(fd, F_GETFL)) == -1) {
            return -1;
    }
    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
            return -1;
    }
    return 0;
}
void ServerRead(int fd, short ev, void *arg)
{
    //1)when telnet on 1999 and send a string,this never prints,help!
    printf("client readblen");
    fflush(stdout);
            struct client *client = (struct client *)arg;
    u_char buf[8196];
    int len, wlen;
    len = read(fd, buf, sizeof(buf));
    if (len == 0) {
            printf("disconnectedn");
            close(fd);
            event_del(&ServerEvent);
            free(client);
            return;
    } else if (len < 0) {
            printf("socket fail %sn", strerror(errno));
            close(fd);
            event_del(&ServerEvent);
            free(client);
            return;
    }
    wlen = write(fd, buf, len);//1)client str never echo back
    if (wlen < len) {
            printf("not all data write back to clientn");
    }
}
void ServerWrite(int fd, short ev, void *arg)
{
//2)to be simple,let writer do nothing
/*  if(!arg)
    {
            printf("ServerWrite err!arg nulln");
            return;
    }
    int len=strlen(arg);
    if(len <= 0)
    {
            printf("ServerWrite err!len:%dn",len);
            return;
    }
            int wlen = write(fd, arg, len);
        if (wlen<len) {
                printf("not all data write back to client!wlen:%d len:%d n",wlen,len);
        }
*/
    return;
}

void ServerAccept(int fd, short ev, void *arg)
{
    int cfd;
    struct sockaddr_in addr;
    socklen_t addrlen = sizeof(addr);
    int yes = 1;
    cfd = accept(fd, (struct sockaddr *)&addr, &addrlen);
    if (cfd == -1) {
    //3)this prints ok
            printf("accept(): can not accept client connection");
            return;
    }
    if (SetNonblock(cfd) == -1) {
            close(cfd);
            return;
    }
    if (setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
            printf("setsockopt(): TCP_NODELAY %sn", strerror(errno));
            close(cfd);
            return;
    }
    event_set(&ServerEvent, cfd, EV_READ | EV_PERSIST, ServerRead, NULL);
    event_set(&ServerEvent, cfd, EV_WRITE| EV_PERSIST, ServerWrite,NULL);
    event_add(&ServerEvent, NULL);
    printf("Accepted connection from %s n", (char *)inet_ntoa(addr.sin_addr));
}
int NewSocket(void)
{
    struct sockaddr_in sa;
    ServerSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (ServerSocket == -1) {
            printf("socket(): can not create server socketn");
            return -1;
    }
    if (SetNonblock(ServerSocket) == -1) {
            return -1;
    }
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(ListenPort);
    sa.sin_addr.s_addr = htonl(ListenAddr);
    if (bind(ServerSocket, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
            close(ServerSocket);
            printf("bind(): can not bind server socket");
            return -1;
    }
    if (listen(ServerSocket, MaxConnections) == -1) {
            printf("listen(): can not listen server socket");
            close(ServerSocket);
            return -1;
    }
    event_set(&ServerEvent, ServerSocket, EV_READ | EV_PERSIST, ServerAccept, NULL);
    if (event_add(&ServerEvent, 0) == -1) {
            printf("event_add(): can not add accept event into libevent");
            close(ServerSocket);
            return -1;
    }
    return 0;
}
int main(int argc, char *argv[])
{
    int retval;
    event_init();
    retval = NewSocket();
    if (retval == -1) {
       exit(-1);
    }
    event_dispatch();
    return 0;
}

服务器使用Telnet进行了测试,但客户端没有收到任何消息
问题详细信息作为注释发布在上面的代码中,位于1)、2)、3)。有人能帮我找出为什么读取事件从未被触发吗?

基本上,在您真正想要写入套接字之前,不应该将接受的套接字设置为EV_WRITE。您告诉libevent"让我知道什么时候可以向这个套接字写入",这几乎总是这样。因此ServerWrite是在一个紧密的循环中被调用的。在实践中,您需要EV_WRITE的唯一时间是,如果您正在写入缓冲区,但没有写入所有字节。然后,您需要保存缓冲区的未写入部分,并使用EV_WRITE来发出何时可以再次写入套接字的信号。

相关内容

  • 没有找到相关文章

最新更新