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; }
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); }
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; }
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); }
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; }