static void reset_client(client *c) { ae_delete_file_event(conf.el, c->fd, AE_WRITABLE); ae_delete_file_event(conf.el, c->fd, AE_READABLE); ae_create_file_event(conf.el, c->fd, AE_WRITABLE, write_handler, c); c->written = 0; c->read = 0; }
void free_echoclient(echoclient *c) { if (!c) return ; ae_delete_file_event(c->ev_loop, c->fd, AE_READABLE); ae_delete_file_event(c->ev_loop, c->fd, AE_WRITABLE); close(c->fd); free(c); }
static void free_client(client *c) { dlist_node *node; ae_delete_file_event(conf.el, c->fd, AE_WRITABLE); ae_delete_file_event(conf.el, c->fd, AE_READABLE); close(c->fd); sdsfree(c->obuf); --conf.live_clients; node = dlist_search_key(conf.clients, c); assert(node != NULL); dlist_delete_node(conf.clients, node); free(c); }
int reply_to_client(ae_event_loop *ev_loop, int fd, void *data, int mask) { echoclient *c = (echoclient*)data; strncpy(c->send_buf, c->recv_buf, c->packet_len + 1); int ret, need_write; need_write = c->packet_len + 1 - c->send_buf_len; ret = writen(c, need_write); if (ret == -1) { printf("%s:%d-%d reply to client error\n", c->ip, c->port, c->fd); free_echoclient(c); return -1; }else if (ret == need_write) { c->send_buf[c->packet_len+1] = '\0'; printf("%s:%d-%d reply client send %s\n", c->ip, c->port, c->fd, c->send_buf); if (ae_create_file_event(ev_loop, fd, AE_READABLE, read_from_client, (void*)c) == -1) { printf("%s:%d-%d add reply_to_client event failed\n", c->ip, c->port, c->fd); free_echoclient(c); return -1; } ae_delete_file_event(ev_loop, fd, AE_WRITABLE); reset_echoclient(c); } return 0; }
static void write_handler(ae_event_loop *el, int fd, void *priv, int mask) { client *c = (client *)priv; /* Initialize request when nothing was written. */ if (c->written == 0) { if (conf.requests_issued++ >= conf.requests) { free_client(c); return; } c->start = ustime(); c->latency = -1; } if (sdslen(c->obuf) > c->written) { char *ptr = c->obuf + c->written; int nwritten = write(c->fd, ptr, sdslen(c->obuf) - c->written); if (nwritten == -1) { if (errno != EPIPE) { fprintf(stderr, "write failed:%s\n", strerror(errno)); } free_client(c); return; } c->written += nwritten; if (sdslen(c->obuf) == c->written) { ae_delete_file_event(conf.el, c->fd, AE_WRITABLE); ae_create_file_event(conf.el, c->fd, AE_READABLE, read_handler, c); } } }
int read_from_client(ae_event_loop *ev_loop, int fd, void *data, int mask) { echoclient *c = (echoclient*)data; int ret, need_read; if (c->recv_buf_len == 0) { ret = readn(c, 1);//获取内容长度 if (ret == 0) { return 0; } else if (ret == -1) { printf("%s:%d-%d read from client error\n", c->ip, c->port, c->fd); free_echoclient(c); return -1; }else if (ret == -2) { printf("%s:%d-%d client close connection\n", c->ip, c->port, c->fd); free_echoclient(c); return 0; } c->packet_len = c->recv_buf[0]; } need_read = c->packet_len - c->recv_buf_len + 1 ;//1字节长度 ret = readn(c, need_read); if (ret == 0) { return 0; } else if (ret == -1) { printf("%s:%d-%d read from client error\n", c->ip, c->port, c->fd); free_echoclient(c); return -1; } else if (ret == -2) { printf("%s:%d-%d client close connection\n", c->ip, c->port, c->fd); free_echoclient(c); return 0; } else if (ret == need_read) {//read finish c->recv_buf[c->packet_len+1] = '\0'; printf("%s:%d-%d client send %s\n", c->ip, c->port,c->fd, c->recv_buf); if (ae_create_file_event(ev_loop, fd, AE_WRITABLE, reply_to_client, (void*)c) == -1) { printf("%s:%d-%d add reply_to_client event failed\n", c->ip, c->port, c->fd); free_echoclient(c); return -1; } ae_delete_file_event(ev_loop, fd, AE_READABLE); } return 0; }