/** * new connection */ SWINLINE int swServer_new_connection(swServer *serv, swEvent *ev) { int conn_fd = ev->fd; swConnection* connection = NULL; if(conn_fd > swServer_get_maxfd(serv)) { swServer_set_maxfd(serv, conn_fd); /** * Correction of the number of connections */ if (serv->connect_count > conn_fd) { serv->connect_count = conn_fd; } #ifdef SW_CONNECTION_LIST_EXPAND //新的fd超过了最大fd //需要扩容 if (conn_fd == serv->connection_list_capacity - 1) { void *new_ptr = sw_shm_realloc(serv->connection_list, sizeof(swConnection)*(serv->connection_list_capacity + SW_CONNECTION_LIST_EXPAND)); if(new_ptr == NULL) { swWarn("connection_list realloc fail"); return SW_ERR; } else { serv->connection_list_capacity += SW_CONNECTION_LIST_EXPAND; serv->connection_list = (swConnection *)new_ptr; } } #endif } connection = &(serv->connection_list[conn_fd]); bzero(connection, sizeof(swConnection)); connection->fd = conn_fd; connection->from_id = ev->from_id; connection->from_fd = ev->from_fd; connection->connect_time = SwooleGS->now; connection->last_time = SwooleGS->now; connection->active = 1; //使此连接激活,必须在最后,保证线程安全 return SW_OK; }
static int swServer_master_onClose(swReactor *reactor, swEvent *event) { swServer *serv = reactor->ptr; swConnection *conn; int queue[SW_CLOSE_QLEN]; int i, n, fd; n = serv->main_pipe.read(&serv->main_pipe, queue, sizeof(queue)); if (n <= 0) { swWarn("[Master]main_pipe read failed. Error: %s[%d]", strerror(errno), errno); return SW_ERR; } for (i = 0; i < n / sizeof(int); i++) { fd = queue[i]; conn = swServer_get_connection(serv, fd); if (serv->onMasterClose != NULL) { serv->onMasterClose(serv, fd, conn->from_id); } /** * Reset maxfd, use for connection_list */ if (fd == swServer_get_maxfd(serv)) { int find_max_fd = fd - 1; /** * Find the new max_fd */ for (; serv->connection_list[find_max_fd].active == 0 && find_max_fd > swServer_get_minfd(serv); find_max_fd--); swServer_set_maxfd(serv, find_max_fd); swTrace("set_maxfd=%d|close_fd=%d", find_max_fd, fd); } } return SW_OK; }
/** * close connection */ SWINLINE void swConnection_close(swServer *serv, int fd, int notify) { swConnection *conn = swServer_get_connection(serv, fd); swReactor *reactor; swEvent notify_ev; if(conn == NULL) { swWarn("[Master]connection not found. fd=%d|max_fd=%d", fd, swServer_get_maxfd(serv)); return; } conn->active = 0; int reactor_id = conn->from_id; swCloseQueue *queue = &serv->reactor_threads[reactor_id].close_queue; //将关闭的fd放入队列 queue->events[queue->num] = fd; //增加计数 queue->num ++; reactor = &(serv->reactor_threads[reactor_id].reactor); swTrace("Close Event.fd=%d|from=%d", fd, reactor_id); //释放缓存区占用的内存 if (serv->open_eof_check == 1) { if (conn->in_buffer != NULL) { swBuffer_free(conn->in_buffer); conn->in_buffer = NULL; } } else if (serv->open_length_check == 1) { if (conn->object != NULL) { swString_free(conn->object); } } if (conn->out_buffer != NULL) { swBuffer_free(conn->out_buffer); conn->out_buffer = NULL; } if (conn->in_buffer != NULL) { swBuffer_free(conn->in_buffer); conn->in_buffer = NULL; } //通知到worker进程 if (serv->onClose != NULL && notify == 1) { //通知worker进程 notify_ev.from_id = reactor_id; notify_ev.fd = fd; notify_ev.type = SW_EVENT_CLOSE; SwooleG.factory->notify(SwooleG.factory, ¬ify_ev); } //通知主进程 if (queue->num == SW_CLOSE_QLEN) { swReactorThread_close_queue(reactor, queue); } #ifdef SW_SOCKET_SET_LINGER struct linger linger; linger.l_onoff = 0; linger.l_linger = 0; if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger)) == -1) { swWarn("setsockopt(SO_LINGER) failed. Error: %s[%d]", strerror(errno), errno); } #endif //关闭此连接,必须放在最前面,以保证线程安全 reactor->del(reactor, fd); }
int swServer_master_onAccept(swReactor *reactor, swEvent *event) { swServer *serv = reactor->ptr; swEvent connEv; struct sockaddr_in client_addr; uint32_t client_addrlen = sizeof(client_addr); int new_fd, ret, reactor_id = 0, i, sockopt; //SW_ACCEPT_AGAIN for (i = 0; i < SW_ACCEPT_MAX_COUNT; i++) { //accept得到连接套接字 #ifdef SW_USE_ACCEPT4 new_fd = accept4(event->fd, (struct sockaddr *)&client_addr, &client_addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC); #else new_fd = accept(event->fd, (struct sockaddr *)&client_addr, &client_addrlen); #endif if (new_fd < 0 ) { switch(errno) { case EAGAIN: return SW_OK; case EINTR: continue; default: swWarn("accept() failed. Error: %s[%d]", strerror(errno), errno); return SW_OK; } } swTrace("[Master] Accept new connection. maxfd=%d|reactor_id=%d|conn=%d", swServer_get_maxfd(serv), reactor->id, new_fd); //too many connection if (new_fd >= serv->max_conn) { swWarn("Too many connections [now: %d].", swServer_get_maxfd(serv)); close(new_fd); return SW_OK; } //TCP Nodelay if (serv->open_tcp_nodelay == 1) { sockopt = 1; setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, &sockopt, sizeof(sockopt)); } #ifdef SO_KEEPALIVE //TCP keepalive if (serv->open_tcp_keepalive == 1) { int keepalive = 1; int keep_idle = serv->tcp_keepidle; int keep_interval = serv->tcp_keepinterval; int keep_count = serv->tcp_keepcount; #ifdef TCP_KEEPIDLE setsockopt(new_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive , sizeof(keepalive)); setsockopt(new_fd, IPPROTO_TCP, TCP_KEEPIDLE, (void*)&keep_idle , sizeof(keep_idle)); setsockopt(new_fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keep_interval , sizeof(keep_interval)); setsockopt(new_fd, IPPROTO_TCP, TCP_KEEPCNT, (void *)&keep_count , sizeof(keep_count)); #endif } #endif #if SW_REACTOR_SCHEDULE == 1 //轮询分配 reactor_id = (serv->reactor_round_i++) % serv->reactor_num; #elif SW_REACTOR_SCHEDULE == 2 //使用fd取模来散列 reactor_id = new_fd % serv->reactor_num; #else //平均调度法 reactor_id = serv->reactor_next_i; if (serv->reactor_num > 1 && (serv->reactor_schedule_count++) % SW_SCHEDULE_INTERVAL == 0) { swServer_reactor_schedule(serv); } #endif connEv.type = SW_EVENT_CONNECT; connEv.from_id = reactor_id; connEv.fd = new_fd; connEv.from_fd = event->fd; //add to connection_list swServer_new_connection(serv, &connEv); memcpy(&serv->connection_list[new_fd].addr, &client_addr, sizeof(client_addr)); /* * [!!!] new_connection function must before reactor->add */ ret = serv->reactor_threads[reactor_id].reactor.add(&(serv->reactor_threads[reactor_id].reactor), new_fd, SW_FD_TCP | SW_EVENT_READ); if (ret < 0) { close(new_fd); return SW_OK; } else { if (serv->onMasterConnect != NULL) { serv->onMasterConnect(serv, new_fd, reactor_id); } if (serv->onConnect != NULL) { serv->factory.notify(&serv->factory, &connEv); } } #ifdef SW_ACCEPT_AGAIN continue; #else break; #endif } return SW_OK; }