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