📄 jk_connect.c
字号:
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 + -