Exemple #1
0
/**
 * 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;
}
Exemple #2
0
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;
}
Exemple #3
0
/**
 * 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, &notify_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);
}
Exemple #4
0
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;
}