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 + -
显示快捷键?