socket.c
来自「Serveez是一个服务器框架」· C语言 代码 · 共 676 行 · 第 1/2 页
C
676 行
return sock->check_request (sock);}/* * Allocate a structure of type @code{svz_socket_t} and initialize its data * fields. Assign some of the default callbacks for TCP connections. */svz_socket_t *svz_sock_alloc (void){ svz_socket_t *sock; char *in; char *out; sock = svz_malloc (sizeof (svz_socket_t)); memset (sock, 0, sizeof (svz_socket_t)); in = svz_malloc (RECV_BUF_SIZE); out = svz_malloc (SEND_BUF_SIZE); sock->proto = SOCK_FLAG_INIT; sock->flags = SOCK_FLAG_INIT | SOCK_FLAG_INBUF | SOCK_FLAG_OUTBUF; sock->userflags = SOCK_FLAG_INIT; sock->file_desc = -1; sock->sock_desc = (SOCKET) -1; sock->pipe_desc[READ] = INVALID_HANDLE; sock->pipe_desc[WRITE] = INVALID_HANDLE; sock->read_socket = svz_tcp_read_socket; sock->write_socket = svz_tcp_write_socket; sock->check_request = svz_sock_detect_proto; sock->disconnected_socket = svz_sock_default_disconnect; sock->recv_buffer = in; sock->recv_buffer_size = RECV_BUF_SIZE; sock->send_buffer = out; sock->send_buffer_size = SEND_BUF_SIZE; sock->last_send = time (NULL); sock->last_recv = time (NULL);#if ENABLE_FLOOD_PROTECTION sock->flood_limit = 100;#endif /* ENABLE_FLOOD_PROTECTION */ return sock;}/* * Resize the send and receive buffers for the socket @var{sock}. * @var{send_buf_size} is the new size for the send buffer, * @var{recv_buf_size} for the receive buffer. Note that data may be lost * when the buffers shrink. */int svz_sock_resize_buffers (svz_socket_t *sock, int send_buf_size, int recv_buf_size){ char *send, *recv; if (sock->send_buffer_size != send_buf_size) send = svz_realloc (sock->send_buffer, send_buf_size); else send = sock->send_buffer; if (sock->recv_buffer_size != recv_buf_size) recv = svz_realloc (sock->recv_buffer, recv_buf_size); else recv = sock->recv_buffer; sock->send_buffer = send; sock->recv_buffer = recv; sock->send_buffer_size = send_buf_size; sock->recv_buffer_size = recv_buf_size; return 0;}/* * Free the socket structure @var{sock}. Return a non-zero value on error. */intsvz_sock_free (svz_socket_t *sock){ if (sock->recv_buffer) svz_free (sock->recv_buffer); if (sock->send_buffer) svz_free (sock->send_buffer); if (sock->flags & SOCK_FLAG_LISTENING) { if (sock->data) svz_array_destroy (sock->data); if (sock->port) svz_portcfg_destroy (sock->port); } if (sock->recv_pipe) svz_free (sock->recv_pipe); if (sock->send_pipe) svz_free (sock->send_pipe);#ifdef __MINGW32__ if (sock->overlap[READ]) svz_free (sock->overlap[READ]); if (sock->overlap[WRITE]) svz_free (sock->overlap[WRITE]);#endif /* __MINGW32__ */ svz_free (sock); return 0;}/* * Get local and remote addresses and ports of socket @var{sock} and save * them into the socket structure. */intsvz_sock_intern_connection_info (svz_socket_t *sock){ struct sockaddr_in s; socklen_t size = sizeof (s); unsigned short port; unsigned long addr; if (!getpeername (sock->sock_desc, (struct sockaddr *) &s, &size)) { addr = s.sin_addr.s_addr; port = s.sin_port; } else { addr = INADDR_ANY; port = 0; } sock->remote_port = port; sock->remote_addr = addr; size = sizeof (s); if (!getsockname (sock->sock_desc, (struct sockaddr *) &s, &size)) { addr = s.sin_addr.s_addr; port = s.sin_port; } else { addr = INADDR_ANY; port = 0; } sock->local_port = port; sock->local_addr = addr; return 0;}/* * Get and clear the pending socket error of a given socket. Print * the result to the log file. */intsvz_sock_error_info (svz_socket_t *sock){ int error; socklen_t optlen = sizeof (int); if (getsockopt (sock->sock_desc, SOL_SOCKET, SO_ERROR, (void *) &error, &optlen) < 0) { svz_log (LOG_ERROR, "getsockopt: %s\n", NET_ERROR); return -1; } if (error) {#ifdef __MINGW32__ WSASetLastError (error);#else errno = error;#endif svz_log (LOG_ERROR, "%s\n", NET_ERROR); return -1; } return 0;}/* * Check if a given socket is still valid. Return non-zero if it is * not. */intsvz_sock_valid (svz_socket_t *sock){ if (!(sock->flags & (SOCK_FLAG_LISTENING | SOCK_FLAG_CONNECTED | SOCK_FLAG_CONNECTING))) return -1; if (sock->sock_desc == INVALID_SOCKET) return -1; return 0;}/* * Create a socket structure from the file descriptor @var{fd}. Set the * socket descriptor to non-blocking I/O. Return @code{NULL} on errors. */svz_socket_t *svz_sock_create (int fd){ svz_socket_t *sock; if (svz_fd_nonblock (fd) != 0) return NULL; if (svz_fd_cloexec (fd) != 0) return NULL; if ((sock = svz_sock_alloc ()) != NULL) { svz_sock_unique_id (sock); sock->sock_desc = fd; sock->flags |= (SOCK_FLAG_CONNECTED | SOCK_FLAG_SOCK); svz_sock_intern_connection_info (sock); } return sock;}/* * Disconnect the socket @var{sock} from the network and calls the disconnect * function for the socket if set. Return a non-zero value on errors. */intsvz_sock_disconnect (svz_socket_t *sock){ /* shutdown client connection */ if (sock->flags & SOCK_FLAG_CONNECTED) { if (shutdown (sock->sock_desc, 2) < 0) svz_log (LOG_ERROR, "shutdown: %s\n", NET_ERROR); svz_sock_connections--; } /* close the server/client socket */ if (closesocket (sock->sock_desc) < 0) svz_log (LOG_ERROR, "close: %s\n", NET_ERROR);#if ENABLE_DEBUG svz_log (LOG_DEBUG, "socket %d disconnected\n", sock->sock_desc);#endif sock->sock_desc = INVALID_SOCKET; return 0;}/* * Write @var{len} bytes from the memory location pointed to by @var{buf} * to the output buffer of the socket @var{sock}. Also try to flush the * buffer to the socket of @var{sock} if possible. Return a non-zero value * on error, which normally means a buffer overflow. */intsvz_sock_write (svz_socket_t *sock, char *buf, int len){ int ret; int space; if (sock->flags & SOCK_FLAG_KILLED) return 0; while (len > 0) { /* Try to flush the queue of this socket. */ if (sock->write_socket && !sock->unavailable && sock->flags & SOCK_FLAG_CONNECTED && sock->send_buffer_fill) { if ((ret = sock->write_socket (sock)) != 0) return ret; } if (sock->send_buffer_fill >= sock->send_buffer_size) { /* Queue is full, unlucky socket or pipe ... */ if (sock->flags & SOCK_FLAG_SEND_PIPE) svz_log (LOG_ERROR, "send buffer overflow on pipe (%d-%d) (id %d)\n", sock->pipe_desc[READ], sock->pipe_desc[WRITE], sock->id); else svz_log (LOG_ERROR, "send buffer overflow on socket %d (id %d)\n", sock->sock_desc, sock->id); if (sock->kicked_socket) sock->kicked_socket (sock, 1); return -1; } /* Now move as much of BUF into the send queue. */ if (sock->send_buffer_fill + len < sock->send_buffer_size) { memcpy (sock->send_buffer + sock->send_buffer_fill, buf, len); sock->send_buffer_fill += len; len = 0; } else { space = sock->send_buffer_size - sock->send_buffer_fill; memcpy (sock->send_buffer + sock->send_buffer_fill, buf, space); sock->send_buffer_fill += space; len -= space; buf += space; } } return 0;}/* * Print a formatted string on the socket @var{sock}. @var{fmt} is the * printf()-style format string, which describes how to format the optional * arguments. See the printf(3) manual page for details. */intsvz_sock_printf (svz_socket_t *sock, const char *fmt, ...){ va_list args; static char buffer[VSNPRINTF_BUF_SIZE]; unsigned len; if (sock->flags & SOCK_FLAG_KILLED) return 0; va_start (args, fmt); len = svz_vsnprintf (buffer, VSNPRINTF_BUF_SIZE, fmt, args); va_end (args); /* Just to be sure... */ if (len > sizeof (buffer)) len = sizeof (buffer); return svz_sock_write (sock, buffer, len);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?