📄 sflsock.c
字号:
# if (defined (__UTYPE_BEOS))
return (errno);
# else
return (getsockopt ((SOCKET) handle, SOL_SOCKET, SO_ERROR, 0, 0));
# endif
#else
return (0);
#endif
}
/* ---------------------------------------------------------------------[<]-
Function: accept_socket
Synopsis: Accepts a connection on a specified master socket. If you
do not want to wait on this call, use select() to poll the socket until
there is an incoming request, then call accept_socket. Returns the
number of the new slave socket, or INVALID_SOCKET if there was an error
on the accept call. You can handle errors as fatal except for EAGAIN
which indicates that the operation would cause a non-blocking socket to
block (treat EWOULDBLOCK in the same way).
---------------------------------------------------------------------[>]-*/
sock_t
accept_socket (
sock_t master_socket)
{
#if (defined (DOES_SOCKETS))
sock_t
slave_socket; /* Connected slave socket */
struct sockaddr_in
sin; /* Address of connecting party */
argsize_t
sin_length; /* Length of address */
connect_error_value = IP_NOERROR; /* Assume no errors */
sin_length = (int) sizeof (sin);
slave_socket = accept ((SOCKET) master_socket,
(struct sockaddr *) &sin, &sin_length);
/* On non-Windows systems, accept returns -1 in case of error, which */
/* is the same as INVALID_SOCKET. */
# if (defined (__WINDOWS__))
if (slave_socket == INVALID_SOCKET)
{
int sock_errno = WSAGetLastError ();
if (sock_errno == WSAEWOULDBLOCK || sock_errno == WSAEINPROGRESS)
errno = EAGAIN;
}
# endif
if (slave_socket != INVALID_SOCKET)
{
prepare_socket (slave_socket);
ip_sockets++;
}
return (slave_socket);
#else
connect_error_value = IP_NOSOCKETS;
return (INVALID_SOCKET); /* Sockets not supported */
#endif
}
/* ---------------------------------------------------------------------[<]-
Function: connect_error
Synopsis:
Returns the last error code from one of the connection functions. For
portability in a multithreaded environment, call immediately after the
call to the connection function.
---------------------------------------------------------------------[>]-*/
int
connect_error (void)
{
return (connect_error_value);
}
/* ---------------------------------------------------------------------[<]-
Function: get_sock_addr
Synopsis: Builds an address block (struct sockaddr_in) for the local
end of the specified connected socket. Returns 0 if okay, SOCKET_ERROR
if there was an error. If the name argument is not null, looks-up the
host name and returns it. The name is truncated to namesize characters,
including a trailing null character.
---------------------------------------------------------------------[>]-*/
int
get_sock_addr (
sock_t handle, /* Socket to get address for */
struct sockaddr_in *sin, /* Block for formatted address */
char *name, /* Buffer for host name, or NULL */
int namesize /* Size of host name buffer */
)
{
#if (defined (DOES_SOCKETS))
int
rc; /* Return code from call */
struct hostent
*phe; /* Host information entry */
argsize_t
sin_length; /* Length of address */
ASSERT (sin);
/* Get address for local connected socket */
sin_length = sizeof (struct sockaddr_in);
rc = getsockname ((SOCKET) handle, (struct sockaddr *) sin, &sin_length);
/* Translate into host name string, only if wanted */
if (name != NULL && rc == 0)
{
phe = gethostbyaddr ((char *) &sin-> sin_addr,
sizeof (sin-> sin_addr), AF_INET);
if (phe)
{
strncpy (name, phe-> h_name, namesize);
name [namesize - 1] = '\0';
}
}
# if (defined (__WINDOWS__))
return (win_error (rc));
# else
return (rc);
# endif
#else
return ((int) SOCKET_ERROR); /* Sockets not supported */
#endif
}
/* ---------------------------------------------------------------------[<]-
Function: get_peer_addr
Synopsis: Builds an address block (struct sockaddr_in) for the remote
end of the specified connected socket. Returns 0 if okay, SOCKET_ERROR
if there was an error. If the name argument is not null, looks-up the
host name and returns it. The name is truncated to namesize characters,
including a trailing null character.
---------------------------------------------------------------------[>]-*/
int
get_peer_addr (
sock_t handle, /* Socket to get address for */
struct sockaddr_in *sin, /* Block for formatted address */
char *name, /* Buffer for host name, or NULL */
int namesize /* Size of host name buffer */
)
{
#if (defined (DOES_SOCKETS))
int
rc; /* Return code from call */
struct hostent
*phe; /* Host information entry */
argsize_t
sin_length; /* Length of address */
ASSERT (sin);
/* Get address for connected socket peer */
sin_length = sizeof (struct sockaddr_in);
rc = getpeername ((SOCKET) handle, (struct sockaddr *) sin, &sin_length);
/* Translate into host name string, only if wanted */
if (name != NULL && rc == 0)
{
phe = gethostbyaddr ((char *) &sin-> sin_addr,
sizeof (sin-> sin_addr), AF_INET);
if (phe)
{
strncpy (name, phe-> h_name, namesize);
name [namesize - 1] = '\0';
}
}
# if (defined (__WINDOWS__))
return (win_error (rc));
# else
return (rc);
# endif
#else
return ((int) SOCKET_ERROR); /* Sockets not supported */
#endif
}
/* ---------------------------------------------------------------------[<]-
Function: read_TCP
Synopsis:
Reads data from the socket. On UNIX, VMS, OS/2, passes through to the
standard read function; some other systems have particular ways of
accessing sockets. If there is an error on the read 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, and EPIPE or ECONNRESET which indicate that the socket
was closed at the other end. Treat EWOULDBLOCK as EAGAIN.
---------------------------------------------------------------------[>]-*/
int
read_TCP (
sock_t handle, /* Socket handle */
void *buffer, /* Buffer to receive data */
size_t length /* Maximum amount of data to read */
)
{
#if (defined (DOES_SOCKETS))
# if (defined (__UTYPE_BEOS))
return (recv ((SOCKET) handle, buffer, length, 0));
# elif (defined (__UNIX__) || defined (__VMS__) || defined (__OS2__))
return (read ((SOCKET) handle, buffer, length));
# elif (defined (__WINDOWS__))
int
rc; /* Return code from call */
ASSERT (buffer);
rc = recv ((SOCKET) handle, buffer, length, 0);
return (win_error (rc));
# else
# error "No code for function body."
# endif
#else
return ((int) SOCKET_ERROR); /* Sockets not supported */
#endif
}
#if (defined (__WINDOWS__))
/* -------------------------------------------------------------------------
* win_error -- internal
*
* For Winsockets only: fetches real error code and sticks it in errno,
* if the return code from the last call was SOCKET_ERROR. Returns rc.
*/
static int
win_error (int rc)
{
if (rc == (int) SOCKET_ERROR)
errno = winsock_last_error ();
return (rc);
}
#endif
/* ---------------------------------------------------------------------[<]-
Function: write_TCP
Synopsis:
Writes data to the socket. On UNIX, VMS, OS/2, calls the standard
write function; some other systems have particular ways of accessing
sockets. If there is an error on the write 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, and EPIPE or ECONNRESET which indicate that the socket
was closed at the other end. Treat EWOULDBLOCK as EAGAIN.
---------------------------------------------------------------------[>]-*/
int
write_TCP (
sock_t handle, /* Socket handle */
const void *buffer, /* Buffer containing data */
size_t length /* Amount of data to write */
)
{
#if (defined (DOES_SOCKETS))
# if (defined (__UTYPE_BEOS))
return (send ((SOCKET) handle, buffer, length, 0));
# elif (defined (__UNIX__) || defined (__VMS__) || defined (__OS2__))
return (write ((SOCKET) handle, buffer, length));
# elif (defined (__WINDOWS__))
int
rc; /* Return code from call */
ASSERT (buffer);
rc = send ((SOCKET) handle, buffer, length, 0);
return (win_error (rc));
# else
# error "No code for function body."
# endif
#else
return ((int) SOCKET_ERROR); /* Sockets not supported */
#endif
}
/* ---------------------------------------------------------------------[<]-
Function: read_UDP
Synopsis:
Reads data from 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. The function places the remote host and
port in this structure. This lets you reply using write_UDP ().
Generally a server can use unconnected sockets, and a client can use
connected sockets. You can also format an address for a specific host
and port using the address_end_point () function.
If there is an error on the read 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
read_UDP (
sock_t handle, /* Socket handle */
void *buffer, /* Buffer to receive data */
size_t length, /* Maximum amount of data to read */
const struct sockaddr_in *sin /* Block for address, or null */
)
{
#if (defined (DOES_SOCKETS))
argsize_t
sin_length; /* Length of address */
int
flags = 0, /* Flags for call */
rc; /* Return code from call */
ASSERT (buffer);
ASSERT (sin);
sin_length = (int) sizeof (*sin);
if (sin)
/* Read from unconnected UDP socket; we accept the address of the */
/* sending party in the sin argument. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -