Ejemplo n.º 1
0
void master_threads::run_once(ACL_VSTREAM* client)
{
	if (service_on_accept(client) != 0)
		return;

	socket_stream* stream = (socket_stream*) client->context;
	acl_assert(stream);
	ACL_SOCKET fd = stream->sock_handle();
	int   timeout = stream->get_rw_timeout();

	while (true)
	{
		if (ACL_VSTREAM_BFRD_CNT(client) > 0)
		{
			// 当函数返回 1 时表示 client 已经被关闭了
			if (service_main(client, NULL) == 1)
				break;
			continue;
		}

		// acl_read_wait 当 timeout 为 -1 时才是完全阻塞
		// 等待连接有数据可读,当为 0 时则会立即返回,当
		// > 0 时则等待最多指定超时时间
		if(acl_read_wait(fd, timeout > 0 ? timeout : -1) == 0)
			client->sys_read_ready = 1;
		else if (service_on_timeout(client, NULL) == 0)
			continue;
		else
		{
			service_on_close(client, NULL);
			// 删除流对象时会同时关闭套接字
			delete stream;
			break;
		}

		// 当函数返回 1 时表示 client 已经被关闭了
		if (service_main(client, NULL) == 1)
			break;
	}

	if (__count_limit > 0 && __count >= __count_limit)
		__stop = true;
}
Ejemplo n.º 2
0
Archivo: main.c Proyecto: jhomble/redis
static void run_server(const char *addr)
{
    ACL_VSTREAM *sstream = acl_vstream_listen(addr, 128);
    acl_pthread_pool_t *pool;
    CONN *conn;
    acl_pthread_t tid;
    acl_pthread_attr_t attr;
    ACL_VSTREAM *client;

    if (sstream == NULL) {
        acl_msg_error("listen %s error(%s)", addr, acl_last_serror());
        return;
    }

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    printf("listening on %s ...\n", addr);
    pool = acl_thread_pool_create(10, 10);
    while (1) {
        acl_mem_slice_delay_destroy();
        if (acl_read_wait(ACL_VSTREAM_SOCK(sstream), 5) == -1)
            continue;
        client = acl_vstream_accept(sstream, NULL, 0);
        if (client == NULL) {
            acl_msg_error("accept error(%s)", acl_last_serror());
            break;
        }
        acl_tcp_set_nodelay(ACL_VSTREAM_SOCK(client));
        conn = acl_mycalloc(1, sizeof(CONN));
        conn->stream = client;

        if (0)
            thread_run(conn);
        else if (1)
            acl_pthread_create(&tid, &attr, thread_main, conn);
        else
            acl_pthread_pool_add(pool, thread_run, conn);
    }

    acl_vstream_close(sstream);
}
Ejemplo n.º 3
0
socket_stream* server_socket::accept(int timeout /* = 0 */)
{
	if (fd_ == ACL_SOCKET_INVALID)
	{
		logger_error("server socket not opened!");
		return NULL;
	}

	if (block_ && timeout > 0)
	{
		if (acl_read_wait(fd_, timeout) == -1)
			return NULL;
	}

	ACL_SOCKET fd = acl_accept(fd_, NULL, 0, NULL);
	if (fd == ACL_SOCKET_INVALID)
	{
		if (block_)
			logger_error("accept error %s", last_serror());
		else if (last_error() != ACL_EAGAIN
			&& last_error() != ACL_EWOULDBLOCK)
		{
			logger_error("accept error %s", last_serror());
		}
		return NULL;
	}

	socket_stream* client = new socket_stream();
	if (client->open(fd) == false)
	{
		logger_error("create socket_stream error!");
		return NULL;
	}

	if (!unix_sock_)
		acl_tcp_set_nodelay(fd);

	return client;
}
Ejemplo n.º 4
0
static int network_biopair_interop(ACL_SOCKET fd, int timeout, BIO *network_bio)
{
    const char *myname = "network_biopair_interop";
    int     want_write;
    int     num_write;
    int     write_pos;
    int     from_bio;
    int     want_read;
    int     num_read;
    int     to_bio;
    char    buffer[NETLAYER_BUFFERSIZE];

    /*
     * To avoid deadlock, write all pending data to the network before
     * attempting to read from the network.
     */
    while ((want_write = (int) BIO_ctrl_pending(network_bio)) > 0) {
	if (want_write > (int) sizeof(buffer))
	    want_write = (int) sizeof(buffer);
	from_bio = BIO_read(network_bio, buffer, want_write);

	/*
	 * Write the complete buffer contents to the network.
	 */
	for (write_pos = 0; write_pos < from_bio; /* see below */ ) {
	    if (timeout > 0 && acl_write_wait(fd, timeout) < 0)
		return (-1);
	    num_write = acl_socket_write(fd, buffer + write_pos, from_bio - write_pos, 0, 0, 0);
	    if (num_write <= 0) {
		if ((num_write < 0) && (timeout > 0) && (errno == ACL_EAGAIN || errno == ACL_EINTR)) {
		    acl_msg_warn("%s: write() returns EAGAIN on a writable file descriptor!", myname);
		    acl_msg_warn("%s: pausing to avoid going into a tight select/write loop!", myname);
		    sleep(1);
		} else {
		    acl_msg_warn("%s: error writing %d bytes to the network: %s",
			    myname, from_bio - write_pos, acl_last_serror());
		    return (-1);
		}
	    } else {
		write_pos += num_write;
	    }
	}
    }

    /*
     * Read data from the network into the BIO pair.
     */
    while ((want_read = (int) BIO_ctrl_get_read_request(network_bio)) > 0) {
	if (want_read > (int) sizeof(buffer))
	    want_read = (int) sizeof(buffer);
	if (timeout > 0 && acl_read_wait(fd, timeout) < 0)
	    return (-1);
	num_read = acl_socket_read(fd, buffer, want_read, 0, 0, 0);
	if (num_read == 0)
	    /* FIX 200412 Cannot return a zero read count. */
	    return (-1);
	if (num_read < 0) {
	    if ((num_read < 0) && (timeout > 0) && (errno == ACL_EAGAIN || errno == ACL_EINTR)) {
		acl_msg_warn("%s: read() returns EAGAIN on a readable file descriptor!", myname);
		acl_msg_warn("%s: pausing to avoid going into a tight select/write loop!", myname);
		sleep(1);
	    } else {
		acl_msg_warn("%s: error reading %d bytes from the network: %s",
			myname, want_read, acl_last_serror());
		return (-1);
	    }
	} else {
	    to_bio = BIO_write(network_bio, buffer, num_read);
	    if (to_bio != num_read)
		acl_msg_panic("%s: BIO_write error: to_bio != num_read", myname);
	}
    }
    return (0);
}
Ejemplo n.º 5
0
void master_threads2::run_once(ACL_VSTREAM* client)
{
	if (service_on_accept(client) != 0)
	{
		service_on_close(client, NULL);
		acl_vstream_close(client);
		return;
	}

	socket_stream* stream = (socket_stream*) client->context;
	acl_assert(stream);
	ACL_SOCKET fd = stream->sock_handle();
	int   timeout = stream->get_rw_timeout();
	int   ret;

	while (true)
	{
		if (ACL_VSTREAM_BFRD_CNT(client) > 0)
		{
			// 当函数返回 1 时表示 client 已经被关闭了
			if (service_main(client, NULL) == 1)
				break;
			continue;
		}

		// acl_read_wait 当 timeout 为 -1 时才是完全阻塞
		// 等待连接有数据可读,当为 0 时则会立即返回,当
		// > 0 时则等待最多指定超时时间
		if(acl_read_wait(fd, timeout > 0 ? timeout : -1) == 0)
			client->read_ready = 1;
		else if (service_on_timeout(client, NULL) == 0)
			continue;
		else
		{
			service_on_close(client, NULL);

			// stream 对象会在 service_on_close 中被删除,
			// 但在删除时并不会真正关闭套接流,所以需要在
			// 此处关闭套接字流
			acl_vstream_close(client);
			break;
		}

		// 返回 -1 表示需要关闭该客户端连接
		if ((ret = service_main(client, NULL)) == -1)
		{
			service_on_close(client, NULL);

			// stream 对象会在 service_on_close 中被删除,
			// 但在删除时并不会真正关闭套接流,所以需要在
			// 此处关闭套接字流
			acl_vstream_close(client);
			break;
		}

		// service_main 只能返回 0 或 -1
		acl_assert(ret == 0);
	}

	if (__count_limit > 0 && __count >= __count_limit)
		__stop = true;
}