我只是使用libevent编写一个echo服务器,但似乎永远不会触发read事件。代码是:
#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 readble\n");
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("disconnected\n");
close(fd);
event_del(&ServerEvent);
free(client);
return;
} else if (len < 0) {
printf("socket fail %s\n", 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 client\n");
}
}
void ServerWrite(int fd, short ev, void *arg)
{
//2)to be simple,let writer do nothing
/* if(!arg)
{
printf("ServerWrite err!arg null\n");
return;
}
int len=strlen(arg);
if(len <= 0)
{
printf("ServerWrite err!len:%d\n",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 %s\n", 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 socket\n");
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)。 有人可以帮我找出为什么永远不会触发读取事件?
答案 0 :(得分:0)
基本上你不应该将接受的套接字设置为EV_WRITE,直到你真正想要写入套接字。你告诉libevent&#34;让我知道什么时候我可以写这个socket#34;这几乎总是如此。所以ServerWrite是在紧密循环中调用的。实际上,只有在编写缓冲区时才需要EV_WRITE,但是不写入所有字节。然后,您需要保存缓冲区的未写入部分,并使用EV_WRITE发出信号,以便再次写入套接字。