/* When send a package , we can assign the priority : PRIORITY_HIGH or PRIORITY_LOW If socket buffer is empty, write to fd directly. If write a part, append the rest part to high list. (Even priority is PRIORITY_LOW) Else append package to high (PRIORITY_HIGH) or low (PRIORITY_LOW) list. */ static int send_socket(struct socket_server *ss, struct request_send * request, struct socket_message *result, int priority) { int id = request->id; struct socket * s = &ss->slot[id % MAX_SOCKET]; if (s->type == SOCKET_TYPE_INVALID || s->id != id || s->type == SOCKET_TYPE_HALFCLOSE || s->type == SOCKET_TYPE_PACCEPT) { FREE(request->buffer); return -1; } assert(s->type != SOCKET_TYPE_PLISTEN && s->type != SOCKET_TYPE_LISTEN); if (send_buffer_empty(s)) { int n = write(s->fd, request->buffer, request->sz); if (n < 0) { switch (errno) { case EINTR: case EAGAIN: n = 0; break; default: fprintf(stderr, "socket-server: write to %d (fd=%d) error.", id, s->fd); force_close(ss, s, result); return SOCKET_CLOSE; } } if (n == request->sz) { FREE(request->buffer); return -1; } append_sendbuffer(s, request, n); // add to high priority list, even priority == PRIORITY_LOW sp_write(ss->event_fd, s->fd, s, true); } else { if (priority == PRIORITY_LOW) { append_sendbuffer_low(s, request); } else { append_sendbuffer(s, request, 0); } } return -1; }
/* When send a package , we can assign the priority : PRIORITY_HIGH or PRIORITY_LOW If socket buffer is empty, write to fd directly. If write a part, append the rest part to high list. (Even priority is PRIORITY_LOW) Else append package to high (PRIORITY_HIGH) or low (PRIORITY_LOW) list. */ static int send_socket(struct socket_server *ss, struct request_send * request, struct socket_message *result, int priority, const uint8_t *udp_address) { int id = request->id; struct socket * s = &ss->slot[HASH_ID(id)]; struct send_object so; send_object_init(ss, &so, request->buffer, request->sz); if (s->type == SOCKET_TYPE_INVALID || s->id != id || s->type == SOCKET_TYPE_HALFCLOSE || s->type == SOCKET_TYPE_PACCEPT) { so.free_func(request->buffer); return -1; } if (s->type == SOCKET_TYPE_PLISTEN || s->type == SOCKET_TYPE_LISTEN) { fprintf(stderr, "socket-server: write to listen fd %d.\n", id); so.free_func(request->buffer); return -1; } if (send_buffer_empty(s) && s->type == SOCKET_TYPE_CONNECTED) { // 如果已连接且发送缓冲区为空 if (s->protocol == PROTOCOL_TCP) { // 直接写入套接字 int n = write(s->fd, so.buffer, so.sz); if (n<0) { switch(errno) { case EINTR: case AGAIN_WOULDBLOCK: // 信号中断或者缓冲区写满 n = 0; break; default: fprintf(stderr, "socket-server: write to %d (fd=%d) error :%s.\n",id,s->fd,strerror(errno)); force_close(ss,s,result); so.free_func(request->buffer); return SOCKET_CLOSE; } } if (n == so.sz) { // 如果全部发送完,释放数据缓冲区,返回-1 so.free_func(request->buffer); return -1; } // 如果没有发送完,剩余数据放到高优先级写缓冲区链表 append_sendbuffer(ss, s, request, n); // add to high priority list, even priority == PRIORITY_LOW } else { // udp if (udp_address == NULL) { udp_address = s->p.udp_address; } union sockaddr_all sa; socklen_t sasz = udp_socket_address(s, udp_address, &sa); int n = sendto(s->fd, so.buffer, so.sz, 0, &sa.s, sasz); if (n != so.sz) { append_sendbuffer_udp(ss,s,priority,request,udp_address); } else { so.free_func(request->buffer); return -1; } } // 打开事件循环中fd的可写权限 sp_write(ss->event_fd, s->fd, s, true); } else { if (s->protocol == PROTOCOL_TCP) { if (priority == PRIORITY_LOW) { append_sendbuffer_low(ss, s, request); } else { append_sendbuffer(ss, s, request, 0); } } else { if (udp_address == NULL) { udp_address = s->p.udp_address; } append_sendbuffer_udp(ss,s,priority,request,udp_address); } } return -1; }