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

📄 sflsock.c

📁 短小精悍的C语言标准函数库。提供450个以上的可移植的算法和工具代码。
💻 C
📖 第 1 页 / 共 5 页
字号:
        rc = recvfrom ((SOCKET) handle, buffer, length, flags,
                      (struct sockaddr *) sin, &sin_length);
    else
        /*  Read from a connected UDP socket; we don't need to get the       */
        /*  address, since we already know it.                               */
        rc = recv     ((SOCKET) handle, buffer, length, flags);

#   if (defined (__WINDOWS__))
    return (win_error (rc));
#   else
    return (rc);
#   endif
#else
    return ((int) SOCKET_ERROR);        /*  Sockets not supported            */
#endif
}


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

    Synopsis:
    Writes data to a connected or unconnected UDP socket.  To prepare a
    connected UDP socket you call connect_UDP ().  This makes a connection
    to a specific port on a specific host, and returns a socket handle.
    When you call this function with a null value for the address argument,
    it assumes you are using a connected UDP socket.

    To prepare an unconnected UDP socket, call create_socket () with the
    string "udp" as argument.  This returns a sock_t handle that you can
    use in this function.  If you use an unconnected UDP socket you must
    provide an address structure containing a valid host and port.  You can
    get this information from a read_UDP () or through address_end_point ().

    If there is an error on the write this function returns SOCKET_ERROR.
    You can handle errors as fatal except for EAGAIN which indicates that
    the operation would cause a non-blocking socket to block.  Treat
    EWOULDBLOCK as EAGAIN.
    ---------------------------------------------------------------------[>]-*/

int
write_UDP (
    sock_t handle,                      /*  Socket handle                    */
    const void *buffer,                 /*  Buffer containing data           */
    size_t length,                      /*  Amount of data to write          */
    const struct sockaddr_in *sin       /*  Address to send to, or null      */
)
{
#if (defined (DOES_SOCKETS))
    int
        sin_length,                     /*  Length of address                */
        flags = 0,                      /*  Flags for call                   */
        rc;                             /*  Return code from call            */

    ASSERT (buffer);
    ASSERT (sin);
    sin_length = (int) sizeof (*sin);
    if (sin)
        /*  Write to unconnected UDP socket; we provide the address of       */
        /*  the receiving party in the sin argument.                         */
        rc = sendto ((SOCKET) handle, buffer, length, flags,
                    (struct sockaddr *) sin, sin_length);
    else
        /*  Write to a connected UDP socket; we don't need to supply         */
        /*  the address, since we already know it.                           */
        rc = send   ((SOCKET) handle, buffer, length, flags);

#   if (defined (__WINDOWS__))
    return (win_error (rc));
#   else
    return (rc);
#   endif
#else
    return ((int) SOCKET_ERROR);        /*  Sockets not supported            */
#endif
}


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

    Synopsis:
    Closes the socket.  On UNIX, VMS, OS/2 calls the standard close
    function; some other systems have particular ways of accessing sockets.
    If there is an error on the close this function returns SOCKET_ERROR.
    You can handle errors (in sockerrno) as fatal except for EAGAIN which
    indicates that the operation would cause a non-blocking socket to block.
    Treat EWOULDBLOCK as EAGAIN.
    ---------------------------------------------------------------------[>]-*/

int
close_socket (
    sock_t handle                       /*  Socket handle                    */
)
{
#if (defined (DOES_SOCKETS))
#   if (defined (__UNIX__) || defined (__VMS__) || defined (__OS2__))
    if (!socket_is_alive (handle))
        return (0);
    ip_sockets--;
        shutdown (handle, 2); 
    return (close ((SOCKET) handle));

#   elif (defined (__WINDOWS__))
    int
        rc;

    if (!socket_is_alive (handle))
        return (0);
    ip_sockets--;
        shutdown ((SOCKET) handle, 2); 
    rc = closesocket ((SOCKET) handle);
    return (win_error (rc));

#   else
#       error "No code for function body."
#   endif

#elif (defined (FAKE_SOCKETS))
    return (0);                         /*  Okay, closed                     */

#else
    return ((int) SOCKET_ERROR);        /*  Sockets not supported            */
#endif
}

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

    Synopsis: Performs the standard select() call.  Use this in preference
    to select(), as some systems may not be 100% compatible with BSD sockets,
    Uses the same arguments as the select() call, and gives the same return
    codes.  If sockets are not supported, always returns 0.
    ---------------------------------------------------------------------[>]-*/

int
sock_select (int nfds, fd_set *readfds, fd_set *writefds,
             fd_set *errorfds, struct timeval *timeout)
{
#if (defined (DOES_SOCKETS))
    int
        rc = 0;                         /*  Return code from select()        */
    ASSERT (timeout);

#   if (defined (__UTYPE_BEOS))
    /*  BeOS only supports the readfds argument                              */
    rc = select (nfds, FD_SETTYPE readfds, NULL, NULL, timeout);
    if (rc == -1)
        coprintf ("Error after select(): %s", strerror (errno));
    return (rc);
    
#   elif (defined (WIN32))
    /*  Windows occasionally aborts during the select call...                */
    __try {
        rc = select (nfds, FD_SETTYPE readfds, FD_SETTYPE writefds,
                           FD_SETTYPE errorfds, timeout);
    }
    __except (1) {
        coprintf ("select() aborted - arguments: %d, %p, %p, %p, %p",
                     nfds, FD_SETTYPE readfds, FD_SETTYPE writefds,
                           FD_SETTYPE errorfds, timeout);
    }
    return (rc);

#   else
    rc = select (nfds, FD_SETTYPE readfds, FD_SETTYPE writefds,
                       FD_SETTYPE errorfds, timeout);
    return (rc);
#   endif
#else
    return (0);
#endif
}


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

    Synopsis: Returns a string containing the local hostname.  The returned
    string is in a static area.  Only performs the local hostname lookup one
    time; the returned value is cached for later repeated calls to this
    function.  If sockets are not supported, returns the value "localhost".
    ---------------------------------------------------------------------[>]-*/

char *
get_hostname (void)
{
#if (defined (DOES_SOCKETS))
    static char
        host_name [LINE_MAX + 1] = "";

    if (strnull (host_name))
        if (gethostname (host_name, LINE_MAX))
            strcpy (host_name, "localhost");
    return (host_name);
#else
    return ("localhost");
#endif
}


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

    Synopsis: Returns the current the host address as a 4-byte value in
    host format (not network format).  Returns 0x7f000001 (loopback) if
    sockets are not supported or there was an error getting the current
    host IP address.  If there are several IP addresses on the system,
    returns one arbitrary address.
    ---------------------------------------------------------------------[>]-*/

qbyte
get_hostaddr (void)
{
#if (defined (DOES_SOCKETS))
    struct hostent
        *phe;                           /*  Host information entry           */

    phe = gethostbyname (get_hostname ());
    if (phe)
        return (*(qbyte *) (phe-> h_addr_list [0]));
    else
        return (htonl (SOCKET_LOOPBACK));
#else
    return (htonl (SOCKET_LOOPBACK));
#endif
}


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

    Synopsis: Returns a table of all host IP addresses.  The table ends in
    a zero address.  Each address is a 4-byte value in host format.  Returns
    NULL if there was an error.  If sockets are not supported, returns a
    table with the loopback address (127.0.0.1) and a null address.  The
    caller must free the table using mem_free() when finished using it.
    ---------------------------------------------------------------------[>]-*/

qbyte *
get_hostaddrs (void)
{
#if (defined (DOES_SOCKETS))
    int
        addr_count;                     /*  How many addresses do we have    */
    qbyte
        *addr_table;                    /*  Where we store the addresses     */
    struct hostent
        *phe;                           /*  Host information entry           */

    if ((phe = gethostbyname (get_hostname ())) == NULL)
        return (NULL);

    /*  Count the addresses                                                  */
    for (addr_count = 0; phe-> h_addr_list [addr_count]; addr_count++);

    /*  Allocate a table; socket addresses are 4 bytes                       */
    addr_table = mem_alloc (4 * (addr_count + 1));

    /*  Store the addresses                                                  */
    for (addr_count = 0; phe-> h_addr_list [addr_count]; addr_count++)
        addr_table [addr_count]
            = *(qbyte *) (phe-> h_addr_list [addr_count]);

    addr_table [addr_count] = 0;
    return (addr_table);

#else
    qbyte
        *addr_table;                    /*  Where we store the addresses     */

    addr_table = mem_alloc (8);         /*  Addresses are 4 bytes            */
    addr_table [0] = htonl (SOCKET_LOOPBACK);
    addr_table [1] = 0;
    return (addr_table);
#endif
}


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

    Synopsis: Converts an IP address in network order to a string in dotted
    format.  The string is stored in a statically-allocated buffer that is
    overwritten by each call.
    ---------------------------------------------------------------------[>]-*/

char *
sock_ntoa (qbyte address)
{
    static char
        string [16];                    /*  xxx.xxx.xxx.xxx                  */
    byte
        *part;

    /*  Network order is high-low so we can address the bytes in order       */
    part = (byte *) &address;
    snprintf (string, sizeof (string), 
              "%d.%d.%d.%d", part [0], part [1], part [2], part [3]);
    return (string);
}


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

    Synopsis:
    Returns a string describing the cause of the last fatal error to occur
    a socket.  Should be called directly after a socket i/o operation; if you
    do other i/o operations or allow other threads to proceed in the meantime,
    the returned string may be incorrect.
    ---------------------------------------------------------------------[>]-*/

const char *
sockmsg (void)
{
#if (defined (__WINDOWS__))
    char
        *message;

    switch (WSAGetLastError ())
      {
        case WSAEINTR:           message = "WSAEINTR";           break;
        case WSAEBADF:           message = "WSAEBADF";           break;
        case WSAEACCES:          message = "WSAEACCES";          break;
        case WSAEFAULT:          message = "WSAEFAULT";          break;
        case WSAEINVAL:          message = "WSAEINVAL";          break;
        case WSAEMFILE:          message = "WSAEMFILE";          break;
        case WSAEWOULDBLOCK:     message = "WSAEWOULDBLOCK";     break;
        case WSAEINPROGRESS:     message = "WSAEINPROGRESS";     break;
        case WSAEALREADY:        message = "WSAEALREADY";        break;
        case WSAENOTSOCK:        message = "WSAENOTSOCK";        break;
        case WSAEDESTADDRREQ:    message = "WSAEDESTADDRREQ";    break;
        case WSAEMSGSIZE:        message = "WSAEMSGSIZE";        break;
        case WSAEPROTOTYPE:      message = "WSAEPROTOTYPE";      break;
        case WSAENOPROTOOPT:     message = "WSAENOPROTOOPT";     break;
        case WSAEPROTONOSUPPORT: message = "WSAEPROTONOSUPPORT"; break;
        case WSAESOCKTNOSUPPORT

⌨️ 快捷键说明

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