This section is documentation for the InterNiche Sockets layer. Sockets is an API, primarily used today for TCP programming, which was developed during the early 1980s at U.C. Berkeley for UNIX. Dozens of books and tutorials are available for Sockets programming (one of the compelling arguments for their use), so this section is devoted to functional descriptions of the Sockets subset as supported by the InterNiche TCP/IP stack. It is not a tutorial.
Programmers new to Sockets may observe that there is a good deal of extra "baggage" here not required for a TCP API. There are historical reasons for this. When Sockets was developed, it was fashionable in academic computing to view all IO devices as a file-system-like, (or "streaming") device. This was, obviously, in the days before mice and GUIs. Sockets were initially developed to allow inter-process communication via stream devices - one process would write to a connection socket and another process would read what was written. Sockets was meant to be a one-size-fits-all solution for data IO. On many UNIX systems you can actually pass a socket to the read()
and write()
calls in place of a file descriptor. When the Berkeley researchers wanted to extend the endpoints of the socket outside the host system so that processes on two separate systems could talk, they implemented TCP (as well as other protocols) under the Sockets. This required extending Sockets to indicate what type of service was desired. The AF_INET
(as opposed to AF_UNIX
) parameter in the t_socket()
call is a vestige of this; as is the multiplicity of overlapping routines such as t_write()
, t_send()
, and t_sendto()
which all do similar things on different types of Sockets.
This use of TCP as a carrier for Sockets was TCP's first major popular application outside of the DARPA projects where it was developed. So in a very real sense, TCP owes its widespread popularity today to Berkeley UNIX and Sockets.
Over the years, many simpler, cleaner TCP APIs have been proposed, but, by the time TCP became popular on non-UNIX platforms, it was too late. As with the attempts in the 1970s to switch the United States to the metric system, people had become accustomed to the status quo and were unwilling to switch. Sockets had become entrenched.
So for better or worse, Sockets is the de-facto standard for TCP programming. For all its warts, it still compares favorably with many of the baroque API standards from big commercial software vendors.
The calls documented in this section are compatible with those on UNIX systems insofar as TCP use goes. Example networking code from other Sockets-based systems should work here, and most of what is in the books and tutorials apply as well. We've tried to update the man-pages herein to reflect any differences there are.
One general difference is that all the function names in the InterNiche package start with "t_
", e.g. socket()
is t_socket()
. This is so that embedded systems which already use some of the socket names will not have a conflict at link time. By adding #define
s in your tcpport.h
file, the original Sockets function names can be used in source code.
Another is the UNIX errno
mechanism has been replaced by an error holder attached to each socket structure and assigned a value whenever an error occurs. Thus when a socket call indicates failure, such as t_socket()
returning -1
, you can examine this member or call t_errno(long s)
to find out what went wrong. Possible values for Sockets errors are listed below. These are a subset of the standard Berkeley errors.
/* BSD Sockets errors */ #define ENOBUFS 1 #define ETIMEDOUT 2 #define EISCONN 3 #define EOPNOTSUPP 4 #define ECONNABORTED 5 #define EWOULDBLOCK 6 #define ECONNREFUSED 7 #define ECONNRESET 8 #define ENOTCONN 9 #define EALREADY 10 #define EINVAL 11 #define EMSGSIZE 12 #define EPIPE 13 #define EDESTADDRREQ 14 #define ESHUTDOWN 15 #define ENOPROTOOPT 16 #define EHAVEOOB 17 #define ENOMEM 18 #define EADDRNOTAVAIL 19 #define EADDRINUSE 20 #define EAFNOSUPPORT 21
extern long t_socket (int, int, int); extern int t_bind (long, struct sockaddr *, int); extern int t_listen (long, int); extern long t_accept (long, struct sockaddr *, int *); extern int t_connect (long, struct sockaddr *, int); extern int t_getpeername (long, struct sockaddr *, int *); extern int t_getsockname (long, struct sockaddr *, int *); extern int t_setsockopt (long, int, int, void *, int); extern int t_getsockopt (long, int, int, void *, int); extern int t_recv (long, char *, int, int); extern int t_send (long, char *, int, int); extern int t_recvfrom (long s, char * buf, int len, int flags, struct sockaddr *, int *); extern int t_sendto (long s, char * buf, int len, int flags, struct sockaddr *, int); extern int t_shutdown (long, int); extern int t_socketclose (long); extern int t_errno (long s); extern int t_select(fd_set * in, fd_set * out, fd_set * ev, long tmo_seconds);
/* Generic/TCP socket options */ #define SO_DEBUG 0x0001 /* turn on debugging info recording */ #define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ #define SO_REUSEADDR 0x0004 /* allow local address reuse */ #define SO_KEEPALIVE 0x0008 /* keep connections alive */ #define SO_DONTROUTE 0x0010 /* just use interface addresses */ #define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ #define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ #define SO_LINGER 0x0080 /* linger on close if data present */ #define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ #define SO_TCPSACK 0x0200 /* Allow TCP SACK */ #define SO_WINSCALE 0x0400 /* Set scaling window option */ #define SO_TIMESTAMP 0x0800 /* Set TCP timestamp option */ #define SO_BIGCWND 0x1000 /* Large initial Congenstion window */ #define SO_HDRINCL 0x2000 /* user access to IP hdr for SOCK_RAW */ #define SO_NOSLOWSTART 0x4000 /* suppress slowstart on this socket */ #define SO_FULLMSS 0x8000 /* force packets to all be MAX size */ #define SO_SNDBUF 0x1001 /* send buffer size */ #define SO_RCVBUF 0x1002 /* receive buffer size */ #define SO_SNDLOWAT 0x1003 /* send low-water mark */ #define SO_RCVLOWAT 0x1004 /* receive low-water mark */ #define SO_SNDTIMEO 0x1005 /* send timeout */ #define SO_RCVTIMEO 0x1006 /* receive timeout */ #define SO_ERROR 0x1007 /* get error status and clear */ #define SO_TYPE 0x1008 /* get socket type */ #define SO_HOPCNT 0x1009 /* Hop count to get to dst */ #define SO_MAXMSG 0x1010 /* get/set TCP_MSS (max segment size) */ #define SO_RXDATA 0x1011 /* get count of bytes in sb_rcv */ #define SO_TXDATA 0x1012 /* get count of bytes in sb_snd */ #define SO_MYADDR 0x1013 /* return my IP address */ #define SO_NBIO 0x1014 /* set socket into NON-blocking mode */ #define SO_BIO 0x1015 /* set socket into blocking mode */ #define SO_NONBLOCK 0x1016 /* set/get blocking mode via param */ #define SO_CALLBACK 0x1017 /* set/get zero_copy callback routine */ /* TCP User-settable options (used with setsockopt). */ #define TCP_ACKDELAYTIME 0x2001 /* Set time for delayed acks */ #define TCP_NODELAY 0x2002 /* suppress delayed ACKs */ #define TCP_MAXSEG 0x2003 /* set maximum segment size */ /* IP socket options */ #define IP_OPTIONS 1 /* buf/ip_opts; set/get IP options */ #define IP_HDRINCL 2 /* int; header is included with data */ #define IP_TOS 3 /* int; IP type of service and preced. */ #define IP_TTL_OPT 4 /* int; IP time to live */ #define IP_RECVOPTS 5 /* bool; receive all IP opts w/dgram */ #define IP_RECVRETOPTS 6 /* bool; receive IP opts for response */ #define IP_RECVDSTADDR 7 /* bool; receive IP dst addr w/dgram */ #define IP_RETOPTS 8 /* ip_opts; set/get IP options */ /* Multicast socket options */ #define IP_MULTICAST_IF 9 /* u_char; set/get IP multicast i/f */ #define IP_MULTICAST_TTL 10 /* u_char; set/get IP multicast ttl */ #define IP_MULTICAST_LOOP 11 /* u_char; set/get IP multicast loopback */ #define IP_ADD_MEMBERSHIP 12 /* ip_mreq; add an IP group membership */ #define IP_DROP_MEMBERSHIP 13 /* ip_mreq; drop an IP group membership */
Name
t_socket()
Syntax
long t_socket (int domain, int type, int protocol);
Description
t_socket()
creates an endpoint for communication and returns a descriptor. The domain
parameter specifies a communications domain within which communication will take place; this selects the protocol
family which should be used. The protocol family generally is the same as the address family for the addresses supplied in later operations on the socket. These families are defined in the include file socket.h
. The only currently understood format is:
PF_INET (ARPA Internet protocols)
The socket has the indicated type, which specifies the semantics of communication. Currently defined types are:
SOCK_STREAM /* TCP*/ SOCK_DGRAM /* UDP */ SOCK_RAW /* IP */
A SOCK_STREAM
type provides sequenced, reliable, two-way connection based byte streams. A SOCK_DGRAM
socket supports datagrams (connectionless, unreliable messages of a fixed, typically small, maximum length). A SOCK_RAW
socket provides lower-layer protocol access.
Sockets of type SOCK_STREAM
are full-duplex byte streams, similar to pipes. A stream socket must be in a connected state before any data may be sent or received on it. A connection to another socket is created with a t_connect()
call. Once connected, data may be transferred using t_send()
and t_recv()
calls. When a session has been completed, a t_socketclose()
may be performed. Out-of-band data may also be transmitted as described in the t_send()
page and received as described in t_recv()
.
The communications protocols used to implement a SOCK_STREAM
ensure that data is not lost or duplicated. If a piece of data for which the peer protocol has buffer space cannot be successfully transmitted within a reasonable length of time, then the connection is considered broken and calls will indicate an error with -1
returns and with ETIMEDOUT
as the specific code in the global variable t_errno
. The protocols optionally keep sockets "warm" by forcing transmissions roughly every minute in the absence of other activity. An error is then indicated if no response can be elicited on an otherwise idle connection for a extended period (such as five minutes).
SOCK_DGRAM
sockets allow sending of datagrams to correspondents named in t_sendto()
calls. Datagrams are generally received with t_recvfrom()
, which returns the next datagram with its return address.
SOCK_RAW
sockets allow the application access to IP-layer protocols with a datagram-like interface; the application specifies the protocol of interest as the protocol
argument to t_socket()
.
The operation of sockets is controlled by socket level options. These options are defined in the file socket.h
. t_getsockopt()
and t_setsockopt()
are used to get and set options, respectively.
The SO_NOSLOWSTART
option suppresses the standard TCP "slow-start" feature. Normally when newly connected, the TCP socket which is passed a large block of data to send (for example an FTP data connection) will send about two full-sized data segments, and then wait for a response form the other side before sending more. If the speed of the response indicates the network can handle more traffic, the connection will send more segments in reply. The number of segments will keep increasing until they are limited by internal resources or the receives window size.
In situations where a machine on an ethernet is sending it's packets through a router to a slower media (i.e. DSL) this slow start behaviour prevents the socket from flooding the router. The SO_NOSLOWSTART
option defeats this feature, allowing the first data burst on the net to be a maximum number of segments allowed.
SO_FULLMSS
prevents the socket from sending any data until the socket has buffered enough data to send a full sized packet. The size is determined by the network hardware, usually about 1460 data bytes. This should be used judiciously, since it may prevent proper operation of typical network applications. The problem is that an application command will not be sent until enough commands are buffered to produce the full-sized packet. For applications like FTP and HTTP, the average command is much too small to trigger the send. This option will not be available unless the TCP layer has been compiled with the #define SUPPORT_SO_FULLMSS
in ipport.h
.
The TCP_NODELAY
disables the Nagle algorithm, and prevents attempts to coalesce small packets less than the TCP_MSS
, while awaiting acknowledgement for data already sent.
TCP_ACKDELAYTIME
sets the delay time for TCP delayed ACKs. The number of milliseconds of delay is passed to setsockopt()
as a parameter. The millisecond time specified will by rounded off to the nearest "cticks
" value. This option will not be available unless the TCP layer has been compiled with the #define DO_DELAY_ACKS
in ipport.h
. Builds which are compiled with this define will do delayed acks on all sockets by default, with a value of 1 ctick
.
The TCP_NOACKDELAY
option defeats delayed acking on specific sockets and is not be available unless the TCP layer has been compiled with the #define DO_DELAY_ACKS
in ipport.h
. Builds which are compiled with this define will do delayed acks on all sockets by default, with a value of 1 ctick
. Setting TCP_NOACKDELAY
will cause sockets to ack immediately as decided by the TCP code, with no delay.
TCP_MAXSEG
is used to set the TCP MSS (Maximum Segment Size) value of the socket. Normally this value default to the size of the largest datagram supported on the underlying media, minus room for TCP, IP, and media headers. On ethernet this number is 1460 octets. This option can be called anytime after the socket is created, and should be called before the socket is connected. Calling after connection will produce unpredictable results. The value passed should generally be smaller than the default value as larger values may result in IP fragmentation.
Returns
t_socket()
returns a non-negative descriptor on success. On failure, it returns -1
and sets an internal to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
t_accept(), t_bind(), t_connect(), t_getsockname(), t_getsockopt(), t_listen(), t_recv(), t_select(), t_send(), t_shutdown()
Name
t_listen()
Syntax
int t_listen(long s, int backlog);
Description
To accept connections, a socket
is first created with t_socket()
, a backlog for incoming connections is specified with t_listen()
and then the connections are accepted with t_accept()
. The t_listen()
call applies only to sockets of type SOCK_STREAM
. The backlog parameter defines the maximum length for the queue of pending connections (not maximum open connections). If a connection request arrives with the queue full the client will receive an error with an indication of ECONNREFUSED
.
Returns
Returns 0
on success. On failure, it returns -1
and sets an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
Name
t_connect()
Syntax
int t_connect(long s, struct sockaddr *name, int namelen);
Description
The parameter s
is a socket. If it is of type SOCK_DGRAM
or SOCK_RAW
, then this call specifies the peer with which the socket is to be associated; the address is to which datagrams are sent and the only address from which datagrams are received. If it is of type SOCK_STREAM
, then this call attempts to make a connection to another socket. The other socket is specified by name
which is an address in the communications space of the socket. Each communications space interprets the name
parameter in its own way.
Generally, stream sockets may successfully t_connect()
only once, however in the Interniche Sockets implementation even for a streams socket, if NB_CONNECT
is defined in ipport.h_h
or the socket is a non-blocking socket, then a socket allows repeated calls to t_connect()
. These calls will return 0
once the socket is connected, or a SOCKET_ERROR
if it is in the process of connecting.
Datagram and raw sockets may use t_connect()
multiple times to change their association. Datagram and raw sockets may also dissolve the association by connecting to an invalid address, such as a zero address.
Returns
This returns 0
on success. On failure, it returns -1
and sets an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
t_accept(), t_connect(), t_getsockname(), t_select(), t_socket()
Name
t_socketclose()
Syntax
int t_socketclose(long s);
Note: this is just close()
on traditional Sockets systems.
Description
The t_socketclose()
call causes all of a full-duplex connection on the socket associated with s
to be shut down and the socket descriptor associated with s
to be returned to the free socket descriptor pool. Once a socket is closed, no further socket calls should be made with it.
Returns
This returns 0
on success. On failure, it returns -1
and sets an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
Name
t_select()
Syntax
int t_select (fd_set * readfds, fd_set * writefds, fd_set * exceptfds; long tv);
void FD_SET (long so, fd_set * set)
void FD_CLR (long so, fd_set * set)
void FD_ISSET (long so, fd_set * set)
void FD_ZERO (fd_set * set)
Description
t_select()
examines the socket descriptor sets whose addresses are passed in readfds
, writefds
, and exceptfds
to see if some of their descriptors are ready for reading, ready for writing or have an exception condition pending. On return, t_select()
replaces the given descriptor sets with subsets consisting of those descriptors that are ready for the requested operation. The total number of ready descriptors in all the sets is returned. Any of readfds
, writefds
, and exceptfds
may be given as NULL
pointers if no descriptors are of interest. Selecting true for reading on a socket descriptor upon which a t_listen()
call has been performed indicates that a subsequent t_accept()
call on that descriptor will not block.
In the standard Berkeley UNIX Sockets API, the descriptor sets are stored as bit fields in arrays of integers. This works in the UNIX environment because under UNIX socket descriptors are file system descriptors which are guaranteed to be small integers that can be used as indexes into the bit fields. In the InterNiche stack, socket descriptor are pointers and thus a bit field representation of the descriptor sets is not feasible. Because of this, the InterNiche Sockets API differs from the Berkeley standard in that the descriptor sets are represented as instances of the following structure:
typedef struct fd_set { /* the select socket array manager */ unsigned fd_count; /* how many are SET? */ long fd_array[FD_SETSIZE]; /* an array of SOCKETs */ } fd_set;
Instead of a socket descriptor being represented in a descriptor set via an indexed bit, an InterNiche socket descriptor is represented in a descriptor set by its presence in the fd_array
field of the associated fd_set
structure. Despite this non-standard representation of the descriptor sets themselves, the following standard entry points are provided for manipulating such descriptor sets: FD_ZERO(&fdset)
initializes a descriptor set fdset
to the null set. FD_SET(fd, &fdset)
includes a particular descriptor, fd
, in fdset
. FD_CLR(fd, &fdset)
removes fd
from fdset
. FD_ISSET(fd, &fdset)
is nonzero if fd
is a member of fdset
, zero otherwise. These entry points behave according to the standard Berkeley semantics.
The porting engineer should be aware that the value of FD_SETSIZE
defines the maximum number of descriptors that can be represented in a single descriptor set. The default value of FD_SETSIZE
of 12 is defined in tcp/tcpport.h
. This value can be increased to accommodate a larger maximum number of descriptors at the cost of increased processor stack usage.
Another difference between the Berkeley and InterNiche t_select()
calls is the representation of the timeout parameter. Under Berkeley Sockets, the timeout parameter is represented by a pointer to a structure. Under InterNiche Sockets, a timeout is specified by the tv
parameter, which defines the maximum number of seconds that should elapse before the call to t_select()
returns. A tv parameter equal to 0
implies that t_select()
should return immediately (effectively a poll of the sockets in the descriptor sets). Note that there is no provision for no timeout, that is, there is no way to specify that t_select()
block forever unless one of its descriptors becomes ready. The maximum value (the longest time in seconds) that can be specified for the tv
parameter can be calculated by dividing the largest value that can be represented in a variable of type long
by the TPS constant (system ticks per second). On PC based systems where longs are typically 32 bits and TPS is 18, this works out to be over 3 years.
The final difference between the Berkeley and InterNiche versions of t_select()
is the absence in the InterNiche version of the Berkeley width
parameter. The width
parameter is of use only when descriptor sets are represented as bit arrays and was thus deleted in the InterNiche implementation.
Returns
t_select() returns a non-negative value on success. A positive value indicates the number of ready descriptors in the descriptor sets. 0
indicates that the time limit specified by tv
expired.
See Also
t_accept(), t_connect(), t_listen(), t_recv(), t_send()
Notes
Under rare circumstances, t_select()
may indicate that a descriptor is ready for writing when in fact an attempt to write would block. This can happen if system resources necessary for a write are exhausted or otherwise unavailable. If an application deems it critical that writes to a file descriptor not block, it should set the descriptor for non-blocking I/O. See discussion of t_setsockopt().
Name
t_recv()
t_recvfrom()
Syntax
int t_recv(long s, char * buf, int len, int flags);
int t_recvfrom(long s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen);
Description
s
is a socket created with t_socket()
. t_recv()
and t_recvfrom()
are used to receive messages from another socket. t_recv()
may be used only on a connected socket (see t_connect()), while t_recvfrom()
may be used to receive data on a socket whether it is in a connected state or not.
If from
is not a NULL
pointer, the source address of the message is filled in. fromlen
is a value-result parameter, initialized to the size of the buffer associated with from
, and modified on return to indicate the actual size of the address stored there. The length of the message is returned. If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from (see t_socket()).
If no messages are available at the socket, the receive call waits for a message to arrive, unless the socket is non-blocking (see t_setsockopt()) in which case -1
is returned with the external variable t_errno
set to EWOULDBLOCK
.
Note that t_recv()
will return an EPIPE
if an attempt is made to read from an unconnected socket.
The t_select()
call may be used to determine when more data arrive.
The flags
parameter is formed by OR-ing one or more of the following:
MSG_OOB | Read any "out-of-band" data present on the socket, rather than the regular "in-band" data. |
MSG_PEEK | "Peek" at the data present on the socket; the data are returned, but not consumed, so that a subsequent receive operation will see the same data. |
Returns
These calls return the number of bytes received, or -1
if an error occurred. On failure, they set an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
Name
t_send()
t_sendto()
Syntax
int t_send(long s, char *buf, int len, int flags);
int t_sendto(long s, char *buf, int len, int flags, struct sockaddr *to, int tolen);
Description
t_send()
and t_sendto()
are used to transmit the message addressed by buf to another socket. t_send()
may be used only when the socket is in a connected state, while t_sendto()
may be used at any time, in which case the address of the target is given by the to parameter. The length of the message is given by len
.
No indication of failure to deliver is implicit in a t_send()
. Locally detected errors are indicated by a Return Value of -1
.
If no messages space is available at the socket to hold the message to be transmitted, then t_send()
normally blocks, unless the socket has been placed in non-blocking I/O mode. The t_select()
call may be used to determine when it is possible to send more data.
The flags
parameter may include one or more of the following:
#define MSG_OOB 0x1 /* process out-of-band data */ #define MSG_DONTROUTE 0x4 /* bypass routing, use direct interface */
The flag MSG_OOB
is used to send "out-of-band" data on sockets that support this notion (e.g. SOCK_STREAM
); the underlying protocol must also support "out-of-band" data. MSG_DONTROUTE
is usually used only by diagnostic or routing programs.
Returns
The call returns the number of characters sent, or -1
if an error occurred. On failure, it sets an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
Name
t_accept()
Syntax
long t_accept(long s, struct sockaddr *addr, int *addrlen);
Description
The argument s
is a socket that has been created with t_socket()
, bound to an address with t_bind()
and is listening for connections after a t_listen()
. t_accept()
extracts the first connection on the queue of pending connections, creates a new socket with the same properties of s and allocates a new file descriptor for the socket. If no pending connections are present on the queue, and the socket is not marked as non-blocking, t_accept()
blocks the caller until a connection is present. If the socket is marked non-blocking and no pending connections are present on the queue, t_accept()
returns an error as described below. The accepted socket is used to read and write data to and from the socket which connected to this one; it is not used to accept more connections. The original socket s remains open for accepting further connections.
The argument addr
is a result parameter that is filled in with the address of the connecting entity as known to the communications layer, i.e. the exact format of the addr
parameter is determined by the domain in which the communication is occurring. The addrlen
is a value-result parameter. It should initially contain the amount of space pointed to by addr
. On return it will contain the actual length (in bytes) of the address returned. This call is used with connection-based socket types, currently with SOCK_STREAM
.
It is possible to t_select()
a socket for the purposes of doing an t_accept()
by selecting it for read.
Returns
t_accept()
returns a non-negative descriptor for the accepted socket on success. On failure, it returns -1
and sets an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
Name
t_bind()
Syntax
int t_bind(long , struct sockaddr *name, int namelen);
Description
t_bind()
assigns a name to an unnamed socket. When a socket is created with t_socket()
it exists in a name space (address family) but has no name assigned. t_bind()
requests that the name pointed to by name be assigned to the socket.
Returns
t_bind()
returns 0
on success. On failure, it returns -1
and sets an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
Name
t_shutdown()
Syntax
int t_shutdown(long s, int how);
Description
The t_shutdown()
call causes all or part of a full-duplex connection on the socket associated with s
to be shut down. If how
is 0
, then further receives will be disallowed. If how
is 1
, then further sends will be disallowed. If how
is 2
, then further sends and receives will be disallowed.
Returns
This returns 0
on success. On failure, it returns -1
and sets an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
Name
t_getpeername()
Syntax
int t_getpeername(long s, struct sockaddr *name, int * addrlen);
Description
Fills in the passed struct sockaddr
with the IP addressing information of the connected host.
Returns
This returns 0
on success. On failure, it returns -1
and sets an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
Name
t_getsockname()
Syntax
int t_getsockname(long s, struct sockaddr *name, int * addrlen);
Description
t_getsockname()
returns the current name for the specified socket, in the passed struct sockaddr
.
Returns
This returns 0
on success. On failure, it returns -1
and sets an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also
Name
t_getsockopt()
t_setsockopt()
Syntax
int t_getsockopt(long s, int level, int optname, char *optval, int optlen);
int t_setsockopt(long s, int level, int optname, char *optval, int optlen);
Description
t_getsockopt()
and t_setsockopt()
manipulate options associated with a socket. The optname
parameter identifies an option that is to be set with t_setsockopt()
or retrieved with t_getsockopt()
.
The parameter optval
is used to specify option values for t_setsockopt()
. On calls to t_setsockopt()
it generally contains a pointer to a variable or structure, the contents of which will define the value of the option to be set. On calls to t_getsockopt()
it generally points to a variable or structure into which the value for the requested option is to be returned.
The include file socket.h
contains definitions for option names, described below. Most options take a pointer to an int variable for optval
. For t_setsockopt()
, the variable addressed by the parameter should be non-zero to enable a Boolean option or zero if the option is to be disabled.
SO_LINGER
uses a struct linger
parameter defined in socket.h
. This parameter specifies the desired state of the option and the linger interval (see below).
In addition to those referenced in section 5.4 (Quick List for Socket Options), the following options are recognized by the InterNiche stack. Except as noted, each may be examined with t_getsockopt()
and set with t_setsockopt()
.
SO_DEBUG | toggle recording of debugging information |
SO_REUSEADDR | toggle local address reuse |
SO_KEEPALIVE | toggle keep connections alive |
SO_DONTROUTE | toggle routing bypass for outgoing messages |
SO_LINGER | linger on close if data present |
SO_BROADCAST | toggle permission to transmit broadcast messages |
SO_OOBINLINE | toggle reception of out-of-band data in band |
SO_SNDBUF | set buffer size for output |
SO_RCVBUF | set buffer size for input |
SO_TYPE | get the type of the socket (get only) |
SO_ERROR | get and clear error on the socket (get only) |
SO_CALLBACK | set a callback function for the socket (set only) |
IP_HDRINCL | set inclusion of IP header in data (SOCK_RAW only) |
SO_DEBUG | enables debugging in the underlying protocol modules. SO_REUSEADDRindicates that the rules used in validating addresses supplied in at_bind() call should allow reuse of local addresses. SO_KEEPALIVE enables the periodic transmission of messages on a connected socket. Should the connected party fail to respond to these messages, the connection is considered broken. If the process is waiting in t_select() when the connection is broken, t_select() returns true for any read or write events selected for the socket. SO_DONTROUTE indicates that outgoing messages should bypass the standard routing facilities. Instead, messages are directed to the appropriate network interface according to the network portion of the destination address. |
SO_LINGER | controls the action taken when unsent messages are queued on socket and a t_socketclose() is performed. If the socket promises reliable delivery of data and SO_LINGER is set, the system will block the caller on the t_socketclose() attempt until it is able to transmit the data or until it decides it is unable to deliver the information (a timeout period, termed the linger interval , is specified in the t_setsockopt() call when SO_LINGER is requested). If SO_LINGER is disabled and a t_socketclose() is issued, the system will process the close in a manner that allows the caller to continue as quickly as possible. |
The option SO_BROADCAST
requests permission to send broadcast datagrams on the socket. Note that the InterNiche stack supports the setting and getting of this option for compatibility but does not check its value when transmitting broadcast messages.
With protocols that support out-of-band data, the SO_OOBINLINE
option requests that out-of-band data be placed in the normal data input queue as received. It will then be accessible with t_recv()
calls without the MSG_OOB
flag. SO_SNDBUF
and SO_RCVBUF
are options to adjust the normal buffer sizes allocated for the output and input buffers respectively. The buffer size may be increased for high-volume connections or may be decreased to limit the possible backlog of incoming data. The system places an absolute limit on these values.
SO_TYPE
and SO_ERROR
are options used only with t_getsockopt()
. SO_TYPE
returns the type of the socket, for example SOCK_STREAM
. SO_ERROR
returns any pending error on the socket and clears the error status. It may be used to check for asynchronous errors on connected datagram sockets or for other asynchronous errors.
The IP_HDRINCL
option is used only with sockets of type SOCK_RAW
. The option value (pointed to by optval
) is expected to be an integer; if it is non-zero it allows application access to the IP header, meaning that received datagrams include an IP header and sent datagrams are expected to be constructed with an IP header at the start of the buffer passed to the t_send()
function. Its default setting is zero.
The options SO_NONBLOCK
, SO_NBIO
, and SO_BIO
are unique to the InterNiche stack (these options do not appear in the Berkeley Sockets API) and are used to control whether a socket uses blocking or non-blocking IO.
SO_NONBLOCK
allows the caller to specify blocking or non-blocking IO that works the same as the other Boolean socket options. That is, optval
points to an integer value which will contain a non-zero value to set non-blocking IO or a 0
value to reset non-blocking IO. This means that we can get the current blocking or non-blocking status of a socket with t_getsockopt()
.
For compatibility, older InterNiche Sockets options SO_NBIO and SO_BIO are still supported. SO_NBIO
is used to specify that a socket use non-blocking IO. SO_BIO
is used to specify that a socket use blocking IO. The use of t_setsockopt()
to set these options is different than that of the standard Boolean options in that the value in optval is not used. All that is necessary is to specify the appropriate option name in optname.
SO_NBIO | Set socket to use non-blocking IO. |
SO_BIO | Set socket to use blocking IO. |
The SO_CALLBACK
option is also specific to the InterNiche stack and is only available if the stack has been built with the TCP_ZEROCOPY
option enabled. See section 6, "TCP Zero-Copy" for more information about this option.
Returns
These return 0
on success. On failure, they return -1
and set an internal t_errno
to one of the errors listed in section 5.2 to indicate the error. The t_errno
can be retrieved by a call to t_errno(s)
.
See Also