tb_bool_t tb_socket_bsend(tb_socket_ref_t sock, tb_byte_t const* data, tb_size_t size) { // send data tb_size_t send = 0; tb_long_t wait = 0; while (send < size) { // send it tb_long_t real = tb_socket_send(sock, data + send, size - send); // has data? if (real > 0) { send += real; wait = 0; } // no data? wait it else if (!real && !wait) { // wait it wait = tb_socket_wait(sock, TB_SOCKET_EVENT_SEND, -1); tb_check_break(wait > 0); } // failed or end? else break; } return send == size; }
tb_long_t tb_dns_looker_wait(tb_dns_looker_ref_t self, tb_long_t timeout) { // check tb_dns_looker_t* looker = (tb_dns_looker_t*)self; tb_assert_and_check_return_val(looker && looker->sock, -1); // has io event? tb_size_t e = TB_SOCKET_EVENT_NONE; if (!(looker->step & TB_DNS_LOOKER_STEP_NEVT)) { if (!(looker->step & TB_DNS_LOOKER_STEP_REQT)) e = TB_SOCKET_EVENT_SEND; else if (!(looker->step & TB_DNS_LOOKER_STEP_RESP)) e = TB_SOCKET_EVENT_RECV; } // need wait? tb_long_t r = 0; if (e) { // trace tb_trace_d("waiting %p ..", looker->sock); // wait r = tb_socket_wait(looker->sock, e, timeout); // fail or timeout? tb_check_return_val(r > 0, r); } // ok? return r; }
tb_bool_t tb_socket_brecv(tb_socket_ref_t sock, tb_byte_t* data, tb_size_t size) { // recv data tb_size_t recv = 0; tb_long_t wait = 0; while (recv < size) { // recv it tb_long_t real = tb_socket_recv(sock, data + recv, size - recv); // has data? if (real > 0) { recv += real; wait = 0; } // no data? wait it else if (!real && !wait) { // wait it wait = tb_socket_wait(sock, TB_SOCKET_EVENT_RECV, -1); tb_check_break(wait > 0); } // failed or end? else break; } return recv == size; }
static tb_bool_t tb_demo_http_session_file_send(tb_socket_ref_t sock, tb_file_ref_t file) { // check tb_assert_and_check_return_val(sock && file, tb_false); // send data tb_hize_t send = 0; tb_hize_t size = tb_file_size(file); tb_long_t wait = 0; while (send < size) { // send it tb_hong_t real = tb_socket_sendf(sock, file, send, size - send); // has data? if (real > 0) { send += real; wait = 0; } // no data? wait it else if (!real && !wait) { // wait it wait = tb_socket_wait(sock, TB_SOCKET_EVENT_SEND, TB_DEMO_TIMEOUT); tb_assert_and_check_break(wait >= 0); } // failed or end? else break; } // ok? return send == size; }
static tb_long_t tb_ssl_sock_wait(tb_cpointer_t priv, tb_size_t events, tb_long_t timeout) { // check tb_assert_and_check_return_val(priv, -1); // wait it return tb_socket_wait((tb_socket_ref_t)priv, events, timeout); }
static tb_void_t tb_demo_coroutine_listen(tb_cpointer_t priv) { // TODO: fix thundering herd issues tb_socket_ref_t sock = (tb_socket_ref_t)priv; while (tb_socket_wait(sock, TB_SOCKET_EVENT_ACPT, -1) > 0) { // accept client sockets tb_size_t count = 0; tb_socket_ref_t client = tb_null; while ((client = tb_socket_accept(sock, tb_null))) { // start client connection if (!tb_coroutine_start(tb_null, tb_demo_coroutine_client, client, TB_DEMO_STACKSIZE)) break; count++; } // trace tb_trace_d("[%#x]: listened %lu", tb_thread_self(), count); } }
static tb_bool_t tb_demo_http_session_head_recv(tb_demo_http_session_ref_t session) { // check tb_assert_and_check_return_val(session && session->sock, tb_false); // read data tb_long_t wait = 0; tb_long_t ok = 0; while (!ok) { // read it tb_long_t real = tb_socket_recv(session->sock, session->data, sizeof(session->data)); // has data? if (real > 0) { // get the header line ok = tb_demo_http_session_head_line(session, session->data, real); // clear wait events wait = 0; } // no data? wait it else if (!real && !wait) { // wait it wait = tb_socket_wait(session->sock, TB_SOCKET_EVENT_RECV, TB_DEMO_TIMEOUT); tb_assert_and_check_break(wait >= 0); } // failed or end? else break; } // ok? return ok > 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_void_t tb_demo_coroutine_pull(tb_cpointer_t priv) { // done tb_socket_ref_t sock = tb_null; do { // init socket sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4); tb_assert_and_check_break(sock); // init address tb_ipaddr_t addr; tb_ipaddr_set(&addr, "127.0.0.1", TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4); // trace tb_trace_d("[%p]: connecting %{ipaddr} ..", sock, &addr); // connect socket tb_long_t ok; while (!(ok = tb_socket_connect(sock, &addr))) { // wait it if (tb_socket_wait(sock, TB_SOCKET_EVENT_CONN, TB_DEMO_TIMEOUT) <= 0) break; } // connect ok? tb_check_break(ok > 0); // trace tb_trace_d("[%p]: recving ..", sock); // recv data tb_byte_t data[8192]; tb_hize_t recv = 0; tb_long_t wait = 0; tb_hong_t time = tb_mclock(); while (1) { // read it tb_long_t real = tb_socket_recv(sock, data, sizeof(data)); // trace tb_trace_d("[%p]: recv: %ld, total: %lu", sock, real, recv + (real > 0? real : 0)); // has data? if (real > 0) { recv += real; wait = 0; } // no data? wait it else if (!real && !wait) { // wait it wait = tb_socket_wait(sock, TB_SOCKET_EVENT_RECV, TB_DEMO_TIMEOUT); tb_assert_and_check_break(wait >= 0); } // failed or end? else break; } // trace tb_trace_i("[%p]: recv %llu bytes %lld ms", sock, recv, tb_mclock() - time); } while (0); // exit socket if (sock) tb_socket_exit(sock); sock = tb_null; }