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