⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jk_connect.c

📁 精通tomcat书籍原代码,希望大家共同学习
💻 C
📖 第 1 页 / 共 2 页
字号:
            JK_TRACE_EXIT(l);
            return -1;
        }
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "socket SO_KEEPALIVE set to On");
    }

    if (sock_buf > 0) {
        set = sock_buf;
        /* Set socket send buffer size */
        if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (SET_TYPE)&set,
                        sizeof(set))) {
            JK_GET_SOCKET_ERRNO();
            jk_log(l, JK_LOG_ERROR,
                    "failed setting SO_SNDBUF with errno=%d", errno);
            jk_close_socket(sock);
            JK_TRACE_EXIT(l);
            return -1;
        }
        set = sock_buf;
        /* Set socket receive buffer size */
        if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (SET_TYPE)&set,
                                sizeof(set))) {
            JK_GET_SOCKET_ERRNO();
            jk_log(l, JK_LOG_ERROR,
                    "failed setting SO_RCVBUF with errno=%d", errno);
            jk_close_socket(sock);
            JK_TRACE_EXIT(l);
            return -1;
        }
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "socket SO_SNDBUF and  SO_RCVBUF set to %d",
                   sock_buf);
    }

    if (timeout > 0) {
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
        int tmout = timeout * 1000;
        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
                   (const char *) &tmout, sizeof(int));
        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
                   (const char *) &tmout, sizeof(int));
#elif defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO)
        struct timeval tv;
        tv.tv_sec  = timeout;
        tv.tv_usec = 0;
        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
                   (const void *) &tv, sizeof(tv));
        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
                   (const void *) &tv, sizeof(tv));
#endif
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "timeout %d set for socket=%d",
                   timeout, sock);
    }
#ifdef SO_NOSIGPIPE
    /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
     * sending data to a dead peer. Possibly also existing and in use on other BSD
     * systems?
    */
    set = 1;
    if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set,
                   sizeof(int))) {
        JK_GET_SOCKET_ERRNO();
        jk_log(l, JK_LOG_ERROR,
                "failed setting SO_NOSIGPIPE with errno=%d", errno);
        jk_close_socket(sock);
        JK_TRACE_EXIT(l);
        return -1;
    }
#endif
#ifdef SO_LINGER
    /* Make hard closesocket by disabling lingering */
    li.l_linger = li.l_onoff = 0;
    if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (SET_TYPE)&li,
                   sizeof(li))) {
        JK_GET_SOCKET_ERRNO();
        jk_log(l, JK_LOG_ERROR,
                "failed setting SO_LINGER with errno=%d", errno);
        jk_close_socket(sock);
        JK_TRACE_EXIT(l);
        return -1;
    }
#endif
    /* Tries to connect to Tomcat (continues trying while error is EINTR) */
    if (JK_IS_DEBUG_LEVEL(l))
        jk_log(l, JK_LOG_DEBUG,
                "trying to connect socket %d to %s", sock,
                jk_dump_hinfo(addr, buf));

/* Need more infos for BSD 4.4 and Unix 98 defines, for now only
iSeries when Unix98 is required at compil time */
#if (_XOPEN_SOURCE >= 520) && defined(AS400)
    ((struct sockaddr *)addr)->sa_len = sizeof(struct sockaddr_in);
#endif
    ret = nb_connect(sock, (struct sockaddr *)addr, timeout);
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
    if (ret == SOCKET_ERROR) {
        errno = WSAGetLastError() - WSABASEERR;
    }
#endif /* WIN32 */

    /* Check if we are connected */
    if (ret) {
        jk_log(l, JK_LOG_INFO,
               "connect to %s failed with errno=%d",
               jk_dump_hinfo(addr, buf), errno);
        jk_close_socket(sock);
        sock = -1;
    }
    else {
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG, "socket %d connected to %s",
                   sock, jk_dump_hinfo(addr, buf));
    }
    JK_TRACE_EXIT(l);
    return sock;
}

/** close the socket */

int jk_close_socket(int s)
{
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
    if (s != INVALID_SOCKET)
        return closesocket(s) ? -1 : 0;
#else
    if (s != -1)
        return close(s);
#endif

    return -1;
}

#ifndef MAX_SECS_TO_LINGER
#define MAX_SECS_TO_LINGER 16
#endif
#define SECONDS_TO_LINGER  1

#ifndef SHUT_WR
#ifdef SD_SEND
#define SHUT_WR SD_SEND
#else
#define SHUT_WR 0x01
#endif
#endif
int jk_shutdown_socket(int s)
{
    unsigned char dummy[512];
    int nbytes;
    int ttl = 0;
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
    int tmout = SECONDS_TO_LINGER * 1000;
    if (s == INVALID_SOCKET)
#else
    struct timeval tv;
    if (s < 0)
#endif
        return -1;

    /* Shut down the socket for write, which will send a FIN
     * to the peer.
     */
    if (shutdown(s, SHUT_WR)) {
        return jk_close_socket(s);
    }
#if defined(WIN32)  || (defined(NETWARE) && defined(__NOVELL_LIBC__))
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
               (const char *) &tmout, sizeof(int));
#elif defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO)
    tv.tv_sec  = SECONDS_TO_LINGER;
    tv.tv_usec = 0;
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
               (const void *) &tv, sizeof(tv));
#endif
    /* Read all data from the peer until we reach "end-of-file" (FIN
     * from peer) or we've exceeded our overall timeout. If the client does
     * not send us bytes within12 second, close the connection.
     */
    while (1) {
        nbytes = jk_tcp_socket_recvfull(s, dummy, sizeof(dummy));
        if (nbytes <= 0)
            break;
        ttl += SECONDS_TO_LINGER;
        if (ttl > MAX_SECS_TO_LINGER)
            break;
    }
    return jk_close_socket(s);
}

/** send a long message
 * @param sd  opened socket.
 * @param b   buffer containing the data.
 * @param len length to send.
 * @return    -2: send returned 0 ? what this that ?
 *            -3: send failed.
 *            >0: total size send.
 * @bug       this fails on Unixes if len is too big for the underlying
 *             protocol.
 */
int jk_tcp_socket_sendfull(int sd, const unsigned char *b, int len)
{
    int sent = 0;
    int wr;

    while (sent < len) {
        do {
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
            wr = send(sd, (const char*)(b + sent),
                      len - sent, 0);
            if (wr == SOCKET_ERROR)
                errno = WSAGetLastError() - WSABASEERR;
#else
            wr = write(sd, b + sent, len - sent);
#endif
        } while (wr == -1 && (errno == EINTR || errno == EAGAIN));

        if (wr == -1)
            return (errno > 0) ? -errno : errno;
        else if (wr == 0)
            return JK_SOCKET_EOF;
        sent += wr;
    }

    return sent;
}

/** receive len bytes. Used in ajp_common.
 * @param sd  opened socket.
 * @param b   buffer to store the data.
 * @param len length to receive.
 * @return    <0: receive failed or connection closed.
 *            >0: length of the received data.
 */
int jk_tcp_socket_recvfull(int sd, unsigned char *b, int len)
{
    int rdlen = 0;
    int rd;

    while (rdlen < len) {
        do {
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
            rd = recv(sd, (char *)b + rdlen,
                      len - rdlen, 0);
            /* Assuming SOCKET_ERROR is -1 on NETWARE too */
            if (rd == SOCKET_ERROR)
                errno = WSAGetLastError() - WSABASEERR;
#else
            rd = read(sd, (char *)b + rdlen, len - rdlen);
#endif
        } while (rd == -1 && (errno == EINTR || errno == EAGAIN));

        if (rd == -1)
            return (errno > 0) ? -errno : errno;
        else if (rd == 0)
            return JK_SOCKET_EOF;
        rdlen += rd;
    }

    return rdlen;
}

/**
 * dump a sockaddr_in in A.B.C.D:P in ASCII buffer
 *
 */
char *jk_dump_hinfo(struct sockaddr_in *saddr, char *buf)
{
    unsigned long laddr = (unsigned long)htonl(saddr->sin_addr.s_addr);
    unsigned short lport = (unsigned short)htons(saddr->sin_port);

    sprintf(buf, "%d.%d.%d.%d:%d",
            (int)(laddr >> 24), (int)((laddr >> 16) & 0xff),
            (int)((laddr >> 8) & 0xff), (int)(laddr & 0xff), (int)lport);

    return buf;
}

#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
int jk_is_socket_connected(int sd)
{
    fd_set fd;
    struct timeval tv;
    int rc;

    FD_ZERO(&fd);
    FD_SET(sd, &fd);

    /* Wait one microsecond */
    tv.tv_sec  = 0;
    tv.tv_usec = 1;

    /* If we get a timeout, then we are still connected */
    if ((rc = select(1, &fd, NULL, NULL, &tv)) == 0) {
        errno = 0;
        return 1;
    }
    else {
        if (rc == SOCKET_ERROR)
            errno = WSAGetLastError() - WSABASEERR;
        else
            errno = EOF;
        return 0;
    }
}
#else
int jk_is_socket_connected(int sd)
{
    char test_buffer[1];
    int  rd;
    int  saved_errno;

    errno = 0;
    /* Set socket to nonblocking */
    if (sononblock(sd) != 0)
        return 0;
    do {
        rd = read(sd, test_buffer, 1);
    } while (rd == -1 && errno == EINTR);
    saved_errno = errno;
    soblock(sd);
    if (rd == -1 && saved_errno == EWOULDBLOCK) {
    errno = 0;
        return 1;
    }
    else {
        errno = saved_errno ? saved_errno : EOF;
        return 0;
    }
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -