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

📄 sflsock.c

📁 短小精悍的C语言标准函数库。提供450个以上的可移植的算法和工具代码。
💻 C
📖 第 1 页 / 共 5 页
字号:

    ASSERT (protocol && *protocol);
    connect_error_value = IP_NOERROR;   /*  Assume no errors                 */

    /*  Map protocol name to protocol number                                 */
    ppe = getprotobyname (protocol);
    if (ppe == NULL)                    /*  Cannot get protocol entry        */
      {
        connect_error_value = IP_BADPROTOCOL;
        return (INVALID_SOCKET);
      }
    /*  Use protocol string to choose a socket type                          */
    if (streq (protocol, "udp"))
        sock_type = SOCK_DGRAM;
    else
        sock_type = SOCK_STREAM;

    /*  Allocate a socket                                                    */
    handle = (sock_t) socket (AF_INET, sock_type, ppe-> p_proto);
    if (handle == INVALID_SOCKET)       /*  Cannot create passive socket     */
      {
        connect_error_value = IP_SOCKETERROR;
        return (INVALID_SOCKET);
      }
#   if (!defined (__WINDOWS__))
    /*  On BSD-socket systems we need to do this to allow the server to
     *  restart on a previously-used socket, without an annoying timeout
     *  of several minutes.  With winsock the reuseaddr option lets the
     *  server work with an already-used socket (!), so we don't do it.
     */
    setsockopt ((SOCKET) handle, SOL_SOCKET, SO_REUSEADDR,
                (char *) &true_value, sizeof (true_value));
#   endif
    prepare_socket (handle);            /*  Ready socket for use             */
    ip_sockets++;
    return (handle);

#elif (defined (FAKE_SOCKETS))
    return (1);                         /*  Return dummy handle              */

#else
    connect_error_value = IP_NOSOCKETS;
    return (INVALID_SOCKET);            /*  Sockets not supported            */
#endif
}


#if (defined (DOES_SOCKETS))
/*  -------------------------------------------------------------------------
 *  prepare_socket -- internal
 *
 *  Does any system-specific work required to prepare a socket for normal
 *  use.  In Windows we have to set the socket to nonblocking mode.  In
 *  UNIX we do this if the ip_nonblock flag is set.
 */

static void
prepare_socket (sock_t handle)
{
#if (defined (__WINDOWS__))
    u_long
        command = ip_nonblock? 1: 0;

    /*  Redirect events and set non-blocking mode                            */
    if (handle != INVALID_SOCKET)
        ioctlsocket ((SOCKET) handle, FIONBIO, &command);

#elif (defined (__UTYPE_BEOS))
    setsockopt ((SOCKET) handle, SOL_SOCKET, SO_NONBLOCK,
                (void *) &ip_nonblock, sizeof (ip_nonblock));

#elif (defined (__UNIX__) || defined (__OS2__))
    if (ip_nonblock)
        fcntl ((SOCKET) handle, F_SETFL, O_NONBLOCK
                | fcntl (handle, F_GETFL, 0));
#endif
}
#endif


/*  ---------------------------------------------------------------------[<]-
    Function: connect_TCP

    Synopsis:
    Creates a TCP socket and connects it to a specified host and service.
    Returns a socket number or INVALID_SOCKET.  In that case you can get
    the reason for the error by calling connect_error ().  This may be:
    <TABLE>
    IP_NOSOCKETS        Sockets not supported on this system
    IP_BADHOST          Host is not known
    IP_BADPROTOCOL      Cannot understand protocol name
    IP_SOCKETERROR      Cannot open a socket
    IP_CONNECTERROR     Cannot connect socket
    </TABLE>
    The host name may be a full name, NULL or "" meaning the current host,
    or a dotted-decimal number.  The service may be a defined service, e.g.
    "echo", or a port number, specified as an ASCII string.  See
    connect_socket() for details.

    Single-threaded clients may set ip_nonblock to FALSE and block on all
    read and write operations.   They may use select() if they need to be
    able to time-out during reading/writing.

    Multi-threaded servers should set ip_nonblock to TRUE, and use select()
    to multiplex socket access.  When ip_nonblock is TRUE, connect calls
    will return immediately, and the server should use select() to wait until
    the socket is ready for writing.  On some systems (early Linux?), the
    select() call will fail in this situation.  If you compile with
    -DBLOCKING_CONNECT, connects are done synchronously in all cases.

    Examples:
    sock_t handle;
    handle = connect_TCP ("", "8080");
    handle = connect_TCP (NULL, "echo");
    handle = connect_TCP ("www.imatix.com", "http");
    ---------------------------------------------------------------------[>]-*/

sock_t
connect_TCP (
    const char *host,                   /*  Host name                        */
    const char *service                 /*  Service name                     */
)
{
    ASSERT (service && *service);
    return (connect_socket (host,       /*  We have a host name              */
                            service,    /*  We have a service name           */
                            "tcp",      /*  Protocol is TCP                  */
                            NULL,       /*  No prepared address              */
                            3, 0));     /*  3 retries, no waiting            */
}


/*  ---------------------------------------------------------------------[<]-
    Function: connect_UDP

    Synopsis:
    Creates a UDP socket and connects it to a specified host and service.
    Returns a socket number or INVALID_SOCKET.  In that case you can get
    the reason for the error by calling connect_error ().  This may be:
    <TABLE>
    IP_NOSOCKETS        Sockets not supported on this system
    IP_BADHOST          Host is not known
    IP_BADPROTOCOL      Cannot understand protocol name
    IP_SOCKETERROR      Cannot open a socket
    IP_CONNECTERROR     Cannot connect socket
    </TABLE>
    The host name may be a full name, NULL or "" meaning the current host,
    or a dotted-decimal number.  The service may be a defined service, e.g.
    "echo", or a port number, specified as an ASCII string.  See
    connect_socket() for details.

    Single-threaded clients may set ip_nonblock to FALSE and block on all
    read and write operations.   They may use select() if they need to be
    able to time-out during reading/writing.

    Multi-threaded servers should set ip_nonblock to TRUE, and use select()
    to multiplex socket access.  When ip_nonblock is TRUE, connect calls
    will return immediately, and the server should use select() to wait until
    the socket is ready for writing.  On some systems (early Linux?), the
    select() call will fail in this situation.  If you compile with
    -DBLOCKING_CONNECT, connects are done synchronously in all cases.

    Examples:
    sock_t handle;
    handle = connect_UDP ("", "7");
    handle = connect_UDP (NULL, "echo");
    handle = connect_UDP ("imatix.com", "echo");
    ---------------------------------------------------------------------[>]-*/

sock_t
connect_UDP (
    const char *host,                   /*  Host name                        */
    const char *service                 /*  Service name                     */
)
{
    ASSERT (service && *service);
    return (connect_socket (host,       /*  We have a host name              */
                            service,    /*  We have a service name           */
                            "udp",      /*  Protocol is UDP                  */
                            NULL,       /*  No prepared address              */
                            3, 0));     /*  3 retries, no waiting            */
}


/*  ---------------------------------------------------------------------[<]-
    Function: connect_TCP_fast

    Synopsis: Creates a TCP socket and connects it to a specified host/port
    address.  Returns a socket number or INVALID_SOCKET.  In that case you
    can get the reason for the error by calling connect_error ().  This may
    be:
    <TABLE>
    IP_NOSOCKETS        Sockets not supported on this system
    IP_BADHOST          Host is not known
    IP_BADPROTOCOL      Cannot understand protocol name
    IP_SOCKETERROR      Cannot open a socket
    IP_CONNECTERROR     Cannot connect socket
    </TABLE>
    This function is faster, if you know the host system address and port,
    than connect_TCP() because no translation is needed.
    You can get the host/address structure by calling address_end_point()
    or get_peer_addr().  See connect_socket() for details.
    ---------------------------------------------------------------------[>]-*/

sock_t
connect_TCP_fast (
    const struct sockaddr_in *sin       /*  Socket address structure         */
)
{
    ASSERT (sin);
    return (connect_socket (NULL,       /*  No host name                     */
                            NULL,       /*  No service name                  */
                            "tcp",      /*  Protocol is TCP                  */
                            sin,        /*  We have a prepared address       */
                            1, 0));     /*  1 retry, no waiting              */
}


/*  ---------------------------------------------------------------------[<]-
    Function: connect_UDP_fast

    Synopsis:
    Creates a UDP socket and connects it to a specified host/port address.
    Returns a socket number or INVALID_SOCKET.  In that case you can get
    the reason for the error by calling connect_error ().  This may be:
    <TABLE>
    IP_NOSOCKETS        Sockets not supported on this system
    IP_BADHOST          Host is not known
    IP_BADPROTOCOL      Cannot understand protocol name
    IP_SOCKETERROR      Cannot open a socket
    IP_CONNECTERROR     Cannot connect socket
    </TABLE>
    This function is faster, if you know the host system address and port,
    than connect_UDP() because no translation is needed.
    You can get the host/address structure by calling address_end_point()
    or get_peer_addr().  See connect_socket() for details.
    ---------------------------------------------------------------------[>]-*/

sock_t
connect_UDP_fast (
    const struct sockaddr_in *sin       /*  Socket address structure         */
)
{
    ASSERT (sin);
    return (connect_socket (NULL,       /*  No host name                     */
                            NULL,       /*  No service name                  */
                            "udp",      /*  Protocol is UDP                  */
                            sin,        /*  We have a prepared address       */
                            1, 0));     /*  1 retry, no waiting              */
}


/*  ---------------------------------------------------------------------[<]-
    Function: connect_socket

    Synopsis:
    Makes a connection to a remote TCP or UDP port.  This allows a client
    program to start sending information to a server.  Used by the
    connect_TCP and connect_UDP functions.  Returns a socket number or
    INVALID_SOCKET.  If it returns INVALID_SOCKET, you can get the reason
    for the error by calling connect_error ().  This may be one of:
    <TABLE>
    IP_NOSOCKETS        Sockets not supported on this system
    IP_BADHOST          Host is not known
    IP_BADPROTOCOL      Cannot understand protocol name
    IP_SOCKETERROR      Cannot open a socket
    IP_CONNECTERROR     Cannot connect socket
    </TABLE>
    Always blocks until the connection has been made; i.e. when this
    function returns you can start to read and write on the socket.

    The host name may be a full name, NULL or "" meaning the current host,
    or a dotted-decimal number.  The service may be a defined service, e.g.
    "echo", or a port number, specified as an ASCII string.  Alternatively,
    both these values may be NULL or "", in which case the function uses
    the host_addr argument to supply an address.  If you want to build the
    host_addr structure yourself, use build_sockaddr().

    Single-threaded clients may set ip_nonblock to FALSE and block on all
    read and write operations.   They may use select() if they need to be
    able to time-out during reading/writing.

    Multi-threaded servers should set ip_nonblock to TRUE, and use select()
    to multiplex socket access.  When ip_nonblock is TRUE, connect calls
    will return immediately, and the server should use select() to wait until
    the socket is ready for writing.  On some systems (early Linux?), the
    select() call will fail in this situation.  If you compile with
    -DBLOCKING_CONNECT, connects are done synchronously in all cases.

    Examples:
    struct sockaddr_in
        host_addr;
    sock_t
        handle;
    build_sockaddr (&host_addr, 32_bit_host, 16_bit_port);
    handle = connect_socket (NULL, NULL, "tcp", &host_addr, 3, 0);
    ---------------------------------------------------------------------[>]-*/

sock_t
connect_socket (
    const char *host,                   /*  Name of host, "" = localhost     */
    const char *service,                /*  Service name or port as string   */
    const char *protocol,               /*  Protocol "tcp" or "udp"          */
    const struct sockaddr_in *host_addr, /* Socket address structure         */
    int retries_left,                   /*  Max. number of retries           */
    int retry_delay                     /*  Delay between retries            */
)
{
#if (defined (DOES_SOCKETS))
    struct sockaddr_in
        sin;                            /*  Internet end-point address       */
    sock_t
        handle = 0;                     /*  Created socket                   */
    int
        rc;                             /*  Return code from call            */
    Bool
        old_nonblock;                   /*  Create non-blocking sockets      */

    connect_error_value = IP_NOERROR;   /*  Assume no errors                 */

    /*  Format sockaddr_in port and hostname, and quit if that failed        */
    if (service && strused (service))
      {
        ASSERT (protocol && *protocol);
        if (address_end_point (host, service, protocol, &sin))
            return (INVALID_SOCKET);
      }
    else
      {
        ASSERT (host_addr);
        sin = *host_addr;               /*  Fast connect requested           */
      }
    /*  Connect socket and maybe retry a few times...                        */
    old_nonblock = ip_nonblock;
#   if (defined (BLOCKING_CONNECT))
    ip_nonblock = FALSE;                /*  Block on this socket             */
#   endif

    while (retries_left)
      {
        handle = create_socket (protocol);

⌨️ 快捷键说明

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