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

📄 tcp-socket.c

📁 Serveez是一个服务器框架
💻 C
字号:
/* * tcp-socket.c - TCP socket connection implementation * * Copyright (C) 2000, 2001 Stefan Jahn <stefan@lkcc.org> * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. *  * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING.  If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA.   * * $Id: tcp-socket.c,v 1.9 2001/07/06 22:49:07 ela Exp $ * */#if HAVE_CONFIG_H# include <config.h>#endif#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include <sys/types.h>#include <time.h>#if HAVE_UNISTD_H# include <unistd.h>#endif#if HAVE_SYS_TIME_H# include <sys/time.h>#endif#ifdef __MINGW32__# include <winsock2.h>#endif#ifndef __MINGW32__# include <sys/types.h># include <sys/socket.h># include <netinet/in.h># include <netdb.h>#endif#include "libserveez/util.h"#include "libserveez/socket.h"#include "libserveez/core.h"#include "libserveez/server-core.h"#include "libserveez/tcp-socket.h"/* * Default function for writing to the socket @var{sock}. Simply flushes  * the output buffer to the network. Write as much as possible into the  * socket @var{sock}. Writing is performed non-blocking, so only as much  * as fits into the network buffer will be written on each call. */intsvz_tcp_write_socket (svz_socket_t *sock){  int num_written;  int do_write;  SOCKET desc;  desc = sock->sock_desc;  /*    * Write as many bytes as possible, remember how many were actually    * sent. Limit the maximum sent bytes to SOCK_MAX_WRITE.   */  do_write = sock->send_buffer_fill;  if (do_write > SOCK_MAX_WRITE)    do_write = SOCK_MAX_WRITE;  num_written = send (desc, sock->send_buffer, do_write, 0);  /* Some data has been written. */  if (num_written > 0)    {      sock->last_send = time (NULL);      /*       * Shuffle the data in the output buffer around, so that       * new data can get stuffed into it.       */      svz_sock_reduce_send (sock, num_written);    }  /* Error occurred while sending. */  else if (num_written < 0)    {      svz_log (LOG_ERROR, "tcp: send: %s\n", NET_ERROR);      if (svz_errno == SOCK_UNAVAILABLE)	{	  sock->unavailable = time (NULL) + RELAX_FD_TIME;	  num_written = 0;	}    }  /* If final write flag is set, then schedule for shutdown. */  if (sock->flags & SOCK_FLAG_FINAL_WRITE && sock->send_buffer_fill == 0)    num_written = -1;  /* Return a non-zero value if an error occurred. */  return (num_written < 0) ? -1 : 0;}/* * Default function for reading from the socket @var{sock}. This function  * only reads all data from the socket and calls the @code{check_request()} * function for the socket, if set. Returns -1 if the socket has died,  * returns zero otherwise. */intsvz_tcp_read_socket (svz_socket_t *sock){  int num_read;  int ret;  int do_read;  SOCKET desc;  desc = sock->sock_desc;  /*    * Calculate how many bytes fit into the receive buffer.   */  do_read = sock->recv_buffer_size - sock->recv_buffer_fill;  /*   * Check if enough space is left in the buffer, kick the socket   * if not. The main loop will kill the socket if we return a non-zero   * value.   */  if (do_read <= 0)    {      svz_log (LOG_ERROR, "receive buffer overflow on socket %d\n", desc);      if (sock->kicked_socket)	sock->kicked_socket (sock, 0);      return -1;    }  /*   * Try to read as much data as possible.   */  num_read = recv (desc,		   sock->recv_buffer + sock->recv_buffer_fill, do_read, 0);  /* Error occurred while reading. */  if (num_read < 0)    {      /*       * This means that the socket was shut down. Close the socket in this        * case, which the main loop will do for us if we return a non-zero        * value.       */      svz_log (LOG_ERROR, "tcp: recv: %s\n", NET_ERROR);      if (svz_errno == SOCK_UNAVAILABLE)	num_read = 0;      else	return -1;    }  /* Some data has been read successfully. */  else if (num_read > 0)    {      sock->last_recv = time (NULL);#if ENABLE_FLOOD_PROTECTION      if (svz_sock_flood_protect (sock, num_read))	{	  svz_log (LOG_ERROR, "kicked socket %d (flood)\n", desc);	  return -1;	}#endif /* ENABLE_FLOOD_PROTECTION */      sock->recv_buffer_fill += num_read;      if (sock->check_request)	{	  if ((ret = sock->check_request (sock)) != 0)	    return ret;	}    }  /* The socket was `select ()'ed but there is no data. */  else    {      svz_log (LOG_ERROR, "tcp: recv: no data on socket %d\n", desc);      return -1;    }    return 0;}/* * Create a TCP connection to host @var{host} and set the socket descriptor * in structure @var{sock} to the resulting socket. Return a zero value on  * errors. */svz_socket_t *svz_tcp_connect (unsigned long host, unsigned short port){  SOCKET sockfd;  svz_socket_t *sock;  /* Create a socket. */  if ((sockfd = svz_socket_create (PROTO_TCP)) == (SOCKET) -1)    return NULL;  /* Try connecting. */  if (svz_socket_connect (sockfd, host, port) == -1)    return NULL;  /* Create socket structure and enqueue it. */  if ((sock = svz_sock_alloc ()) == NULL)    {      closesocket (sockfd);      return NULL;    }  svz_sock_unique_id (sock);  sock->sock_desc = sockfd;  sock->flags |= (SOCK_FLAG_SOCK | SOCK_FLAG_CONNECTING);  sock->connected_socket = svz_tcp_default_connect;  svz_sock_enqueue (sock);  return sock;}/* * The default routine for connecting a socket @var{sock}. When we get  * @code{select()}ed or @code{poll()}ed via the @var{WRITE_SET} we simply  * check for network errors, */intsvz_tcp_default_connect (svz_socket_t *sock){  int error;  socklen_t optlen = sizeof (int);  /* check if the socket has been finally connected */  if (getsockopt (sock->sock_desc, SOL_SOCKET, SO_ERROR,		  (void *) &error, &optlen) < 0)    {      svz_log (LOG_ERROR, "getsockopt: %s\n", NET_ERROR);      return -1;    }  /* any errors ? */  if (error)    {#ifdef __MINGW32__      WSASetLastError (error);#else      errno = error;#endif      if (error != SOCK_INPROGRESS && error != SOCK_UNAVAILABLE)	{	  svz_log (LOG_ERROR, "connect: %s\n", NET_ERROR);	  return -1;	}#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "connect: %s\n", NET_ERROR);#endif      return 0;    }  /* successfully connected */  sock->flags |= SOCK_FLAG_CONNECTED;  sock->flags &= ~SOCK_FLAG_CONNECTING;  svz_sock_intern_connection_info (sock);  svz_sock_connections++;  return 0;}

⌨️ 快捷键说明

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