Example #1
0
long StreamSocketImpl::send_bytes(const void* buffer, size_t length, int flags) {
    const char* p = reinterpret_cast<const char*>(buffer);
    long remaining = length;
    long sent = 0;
    const auto blocking = get_blocking();
    while (remaining > 0) {
        auto n = SocketImpl::send_bytes(p, remaining, flags);
        if (n < 0) {
            throw NetException("send_bytes error");
        }
        p += n;
        sent += n;
        remaining -= n;
        if (blocking && remaining > 0) {
            std::this_thread::yield();
        }
        else {
            break;
        }
    }
    return sent;
}
Example #2
0
// timeout (in microseconds)
Socket::Status Socket::connect(const Address& remote_addr, uint16 remote_port, uint32 timeout) {
    create();

    // create the remote address
    sockaddr_in address = priv::SocketImpl::create_addr(remote_addr.to_uint32(), remote_port);

    if (timeout == 0) {
        // connect the socket
        if (::connect(get_handle(), reinterpret_cast<struct sockaddr*>(&address), sizeof(address)) == -1)
            return priv::SocketImpl::get_error();

        return STATUS_DONE;
    } else {
        bool blocking = get_blocking();

        // switch to non-blocking to enable our connection timeout
        if (blocking)
            set_blocking(false);

        // try to connect to the remote address
        if (::connect(get_handle(), reinterpret_cast<struct sockaddr*>(&address), sizeof(address)) >= 0) {
            // we got instantly connected
            return STATUS_DONE;
        }

        Status status = priv::SocketImpl::get_error();

        // if we were in non-blocking mode, return immediatly
        if (!blocking)
            return status;

        // otherwise, wait until something happens to our socket (success, timeout or error)
        if (status == STATUS_NOTREADY) {
            fd_set selector;
            FD_ZERO(&selector);
            FD_SET(get_handle(), &selector);

            timeval time;
            time.tv_sec = static_cast<long>(timeout / 1000000);
            time.tv_usec = static_cast<long>(timeout % 1000000);

            // wait for something to write on our socket (which means that the connection request has returned)
            if (select(static_cast<int>(get_handle() + 1), null, &selector, null, &time) > 0) {
                // at this point the connection may have been either accepted or refused
                // to know whether it's a success or a failure, we must check the address of the connected peer
                if (get_address_remote() != Address::ADDR_NONE) {
                    status = STATUS_DONE;
                } else {
                    status = priv::SocketImpl::get_error();
                }
            } else {
                status = priv::SocketImpl::get_error();
            }
        }

        // switch back to blocking mode
        set_blocking(true);

        return status;
    }
}