jk_connect.c

来自「以便Apache与其他服务进行整合 Mod_JK安装」· C语言 代码 · 共 705 行 · 第 1/2 页

C
705
字号
        return JK_INVALID_SOCKET;    }    if (JK_IS_DEBUG_LEVEL(l))        jk_log(l, JK_LOG_DEBUG,               "socket TCP_NODELAY set to On");    if (keepalive) {        set = 1;        if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (SET_TYPE)&set,                       sizeof(set))) {            jk_log(l, JK_LOG_ERROR,                   "failed setting SO_KEEPALIVE (errno=%d)", errno);            jk_close_socket(sock);            JK_TRACE_EXIT(l);            return JK_INVALID_SOCKET;        }        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 (errno=%d)", errno);            jk_close_socket(sock);            JK_TRACE_EXIT(l);            return JK_INVALID_SOCKET;        }        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 (errno=%d)", errno);            jk_close_socket(sock);            JK_TRACE_EXIT(l);            return JK_INVALID_SOCKET;        }        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 (errno=%d)", errno);        jk_close_socket(sock);        JK_TRACE_EXIT(l);        return JK_INVALID_SOCKET;    }#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 (errno=%d)", errno);        jk_close_socket(sock);        JK_TRACE_EXIT(l);        return JK_INVALID_SOCKET;    }#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 onlyiSeries 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 (errno=%d)",               jk_dump_hinfo(addr, buf), errno);        jk_close_socket(sock);        sock = JK_INVALID_SOCKET;    }    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(jk_sock_t s){    if (IS_VALID_SOCKET(s))#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))        return closesocket(s) ? -1 : 0;#else        return close(s);#endif    return -1;}#ifndef MAX_SECS_TO_LINGER#define MAX_SECS_TO_LINGER 30#endif#define SECONDS_TO_LINGER  2#ifndef SHUT_WR#ifdef SD_SEND#define SHUT_WR SD_SEND#else#define SHUT_WR 0x01#endif#endifint jk_shutdown_socket(jk_sock_t s){    char dummy[512];    int rc = 0;    fd_set rs;    struct timeval tv;    time_t start = time(NULL);    if (!IS_VALID_SOCKET(s))        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);    }    /* Set up to wait for readable data on socket... */    FD_ZERO(&rs);    do {        /* Read all data from the peer until we reach "end-of-file"         * (FIN from peer) or we've exceeded our overall timeout. If the         * backend does not send us bytes within 2 seconds         * (a value pulled from Apache 1.3 which seems to work well),         * close the connection.         */        FD_SET(s, &rs);        tv.tv_sec  = SECONDS_TO_LINGER;        tv.tv_usec = 0;        if (select((int)s + 1, &rs, NULL, NULL, &tv) > 0) {            do {#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))                rc = recv(s, &dummy[0], sizeof(dummy), 0);                /* Assuming SOCKET_ERROR is -1 on NETWARE too */                if (rc == SOCKET_ERROR)                    errno = WSAGetLastError() - WSABASEERR;#else                rc = read(s, &dummy[0], sizeof(dummy));#endif            } while (rc == -1 && (errno == EINTR || errno == EAGAIN));            if (rc <= 0)                break;        }        else            break;    } while (difftime(time(NULL), start) < MAX_SECS_TO_LINGER);    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(jk_sock_t 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(jk_sock_t 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;}int jk_is_socket_connected(jk_sock_t sock){    fd_set fd;    struct timeval tv;    int rc;    FD_ZERO(&fd);    FD_SET(sock, &fd);    /* Initially test the socket without any blocking.     */    tv.tv_sec  = 0;    tv.tv_usec = 0;    do {        rc = select((int)sock + 1, &fd, NULL, NULL, &tv);#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))        errno = WSAGetLastError() - WSABASEERR;#endif        /* Wait one microsecond on next select, if EINTR */        tv.tv_sec  = 0;        tv.tv_usec = 1;    } while (rc == -1 && errno == EINTR);    if (rc == 0) {        /* If we get a timeout, then we are still connected */        return 1;    }    else if (rc == 1) {#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))        u_long nr;        if (ioctlsocket(sock, FIONREAD, &nr) == 0) {            if (WSAGetLastError() == 0)                errno = 0;            else                errno = WSAGetLastError() - WSABASEERR;            return nr == 0 ? 0 : 1;        }        errno = WSAGetLastError() - WSABASEERR;#else        int nr;        if (ioctl(sock, FIONREAD, (void*)&nr) == 0) {            return nr == 0 ? 0 : 1;        }#endif    }    return 0;}

⌨️ 快捷键说明

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