The Internet Namespace

This section describes the details of the protocols and socket naming conventions used in the Internet namespace.

Originally the Internet namespace used only IP version 4 (IPv4). With the growing number of hosts on the Internet, a new protocol with a larger address space was necessary: IP version 6 (IPv6). IPv6 introduces 128-bit addresses (IPv4 has 32-bit addresses) and other features, and will eventually replace IPv4.

To create a socket in the IPv4 Internet namespace, use the symbolic name PF_INET of this namespace as the namespace argument to socket or socketpair. For IPv6 addresses you need the macro PF_INET6. These macros are defined in sys/socket.h. int function>PF_INET/function> This designates the IPv4 Internet namespace and associated family of protocols.

int function>PF_INET6/function> This designates the IPv6 Internet namespace and associated family of protocols.

A socket address for the Internet namespace includes the following components:

You must ensure that the address and port number are represented in a canonical format called network byte order. the section called “Byte Order Conversion”, for information about this.

Internet Socket Address Formats

In the Internet namespace, for both IPv4 (AF_INET) and IPv6 (AF_INET6), a socket address consists of a host address and a port on that host. In addition, the protocol you choose serves effectively as a part of the address because local port numbers are meaningful only within a particular protocol.

The data types for representing socket addresses in the Internet namespace are defined in the header file netinet/in.h. function>struct sockaddr_in/function> This is the data type used to represent socket addresses in the Internet namespace. It has the following members:

sa_family_t sin_family

This identifies the address family or format of the socket address. You should store the value AF_INET in this member. the section called “Socket Addresses”.

struct in_addr sin_addr

This is the Internet address of the host machine. the section called “Host Addresses”, and the section called “Host Names”, for how to get a value to store here.

unsigned short int sin_port

This is the port number. the section called “Internet Ports”.

When you call bind or getsockname, you should specify sizeof (struct sockaddr_in) as the length parameter if you are using an IPv4 Internet namespace socket address.

function>struct sockaddr_in6/function> This is the data type used to represent socket addresses in the IPv6 namespace. It has the following members:

sa_family_t sin6_family

This identifies the address family or format of the socket address. You should store the value of AF_INET6 in this member. the section called “Socket Addresses”.

struct in6_addr sin6_addr

This is the IPv6 address of the host machine. the section called “Host Addresses”, and the section called “Host Names”, for how to get a value to store here.

uint32_t sin6_flowinfo

This is a currently unimplemented field.

uint16_t sin6_port

This is the port number. the section called “Internet Ports”.

Host Addresses

Each computer on the Internet has one or more Internet addresses, numbers which identify that computer among all those on the Internet. Users typically write IPv4 numeric host addresses as sequences of four numbers, separated by periods, as in 128.52.46.32, and IPv6 numeric host addresses as sequences of up to eight numbers separated by colons, as in 5f03:1200:836f:c100::1.

Each computer also has one or more host names, which are strings of words separated by periods, as in mescaline.gnu.org.

Programs that let the user specify a host typically accept both numeric addresses and host names. To open a connection a program needs a numeric address, and so must convert a host name to the numeric address it stands for.

Internet Host Addresses

Each computer on the Internet has one or more Internet addresses, numbers which identify that computer among all those on the Internet.

An IPv4 Internet host address is a number containing four bytes of data. Historically these are divided into two parts, a network number and a local network address number within that network. In the mid-1990s classless addresses were introduced which changed this behavior. Since some functions implicitly expect the old definitions, we first describe the class-based network and will then describe classless addresses. IPv6 uses only classless addresses and therefore the following paragraphs don't apply.

The class-based IPv4 network number consists of the first one, two or three bytes; the rest of the bytes are the local address.

IPv4 network numbers are registered with the Network Information Center (NIC), and are divided into three classes--A, B and C. The local network address numbers of individual machines are registered with the administrator of the particular network.

Class A networks have single-byte numbers in the range 0 to 127. There are only a small number of Class A networks, but they can each support a very large number of hosts. Medium-sized Class B networks have two-byte network numbers, with the first byte in the range 128 to 191. Class C networks are the smallest; they have three-byte network numbers, with the first byte in the range 192-255. Thus, the first 1, 2, or 3 bytes of an Internet address specify a network. The remaining bytes of the Internet address specify the address within that network.

The Class A network 0 is reserved for broadcast to all networks. In addition, the host number 0 within each network is reserved for broadcast to all hosts in that network. These uses are obsolete now but for compatibility reasons you shouldn't use network 0 and host number 0.

The Class A network 127 is reserved for loopback; you can always use the Internet address 127.0.0.1 to refer to the host machine.

Since a single machine can be a member of multiple networks, it can have multiple Internet host addresses. However, there is never supposed to be more than one machine with the same host address.

There are four forms of the standard numbers-and-dots notation for Internet addresses:

a.b.c.d

This specifies all four bytes of the address individually and is the commonly used representation.

a.b.c

The last part of the address, c, is interpreted as a 2-byte quantity. This is useful for specifying host addresses in a Class B network with network address number a.b.

a.b

The last part of the address, b, is interpreted as a 3-byte quantity. This is useful for specifying host addresses in a Class A network with network address number a.

a

If only one part is given, this corresponds directly to the host address number.

Within each part of the address, the usual C conventions for specifying the radix apply. In other words, a leading 0x or 0X implies hexadecimal radix; a leading 0 implies octal; and otherwise decimal radix is assumed.

Classless Addresses

IPv4 addresses (and IPv6 addresses also) are now considered classless; the distinction between classes A, B and C can be ignored. Instead an IPv4 host address consists of a 32-bit address and a 32-bit mask. The mask contains set bits for the network part and cleared bits for the host part. The network part is contiguous from the left, with the remaining bits representing the host. As a consequence, the netmask can simply be specified as the number of set bits. Classes A, B and C are just special cases of this general rule. For example, class A addresses have a netmask of 255.0.0.0 or a prefix length of 8.

Classless IPv4 network addresses are written in numbers-and-dots notation with the prefix length appended and a slash as separator. For example the class A network 10 is written as 10.0.0.0/8.

IPv6 Addresses

IPv6 addresses contain 128 bits (IPv4 has 32 bits) of data. A host address is usually written as eight 16-bit hexadecimal numbers that are separated by colons. Two colons are used to abbreviate strings of consecutive zeros. For example, the IPv6 loopback address 0:0:0:0:0:0:0:1 can just be written as ::1.

Host Address Data Type

IPv4 Internet host addresses are represented in some contexts as integers (type uint32_t). In other contexts, the integer is packaged inside a structure of type struct in_addr. It would be better if the usage were made consistent, but it is not hard to extract the integer from the structure or put the integer into a structure.

You will find older code that uses unsigned long int for IPv4 Internet host addresses instead of uint32_t or struct in_addr. Historically unsigned long int was a 32-bit number but with 64-bit machines this has changed. Using unsigned long int might break the code if it is used on machines where this type doesn't have 32 bits. uint32_t is specified by Unix98 and guaranteed to have 32 bits.

IPv6 Internet host addresses have 128 bits and are packaged inside a structure of type struct in6_addr.

The following basic definitions for Internet addresses are declared in the header file netinet/in.h: function>struct in_addr/function> This data type is used in certain contexts to contain an IPv4 Internet host address. It has just one field, named s_addr, which records the host address number as an uint32_t.

uint32_t function>INADDR_LOOPBACK/function> You can use this constant to stand for "the address of this machine," instead of finding its actual address. It is the IPv4 Internet address 127.0.0.1, which is usually called localhost. This special constant saves you the trouble of looking up the address of your own machine. Also, the system usually implements INADDR_LOOPBACK specially, avoiding any network traffic for the case of one machine talking to itself.

uint32_t function>INADDR_ANY/function> You can use this constant to stand for "any incoming address" when binding to an address. the section called “Setting the Address of a Socket”. This is the usual address to give in the sin_addr member of struct sockaddr_in when you want to accept Internet connections.

uint32_t function>INADDR_BROADCAST/function> This constant is the address you use to send a broadcast message.

uint32_t function>INADDR_NONE/function> This constant is returned by some functions to indicate an error.

function>struct in6_addr/function> This data type is used to store an IPv6 address. It stores 128 bits of data, which can be accessed (via a union) in a variety of ways.

struct in6_addr function>in6addr_loopback/function> This constant is the IPv6 address ::1, the loopback address. See above for a description of what this means. The macro IN6ADDR_LOOPBACK_INIT is provided to allow you to initialize your own variables to this value.

struct in6_addr function>in6addr_any/function> This constant is the IPv6 address ::, the unspecified address. See above for a description of what this means. The macro IN6ADDR_ANY_INIT is provided to allow you to initialize your own variables to this value.

Host Address Functions

These additional functions for manipulating Internet addresses are declared in the header file arpa/inet.h. They represent Internet addresses in network byte order, and network numbers and local-address-within-network numbers in host byte order. the section called “Byte Order Conversion”, for an explanation of network and host byte order.

int function>inet_aton/function> (const char *name, struct in_addr *addr) This function converts the IPv4 Internet host address name from the standard numbers-and-dots notation into binary data and stores it in the struct in_addr that addr points to. inet_aton returns nonzero if the address is valid, zero if not.

uint32_t function>inet_addr/function> (const char *name) This function converts the IPv4 Internet host address name from the standard numbers-and-dots notation into binary data. If the input is not valid, inet_addr returns INADDR_NONE. This is an obsolete interface to inet_aton, described immediately above. It is obsolete because INADDR_NONE is a valid address (255.255.255.255), and inet_aton provides a cleaner way to indicate error return.

uint32_t function>inet_network/function> (const char *name) This function extracts the network number from the address name, given in the standard numbers-and-dots notation. The returned address is in host order. If the input is not valid, inet_network returns -1.

The function works only with traditional IPv4 class A, B and C network types. It doesn't work with classless addresses and shouldn't be used anymore.

char * function>inet_ntoa/function> (struct in_addr addr) This function converts the IPv4 Internet host address addr to a string in the standard numbers-and-dots notation. The return value is a pointer into a statically-allocated buffer. Subsequent calls will overwrite the same buffer, so you should copy the string if you need to save it.

In multi-threaded programs each thread has an own statically-allocated buffer. But still subsequent calls of inet_ntoa in the same thread will overwrite the result of the last call.

Instead of inet_ntoa the newer function inet_ntop which is described below should be used since it handles both IPv4 and IPv6 addresses.

struct in_addr function>inet_makeaddr/function> (uint32_t net, uint32_t local) This function makes an IPv4 Internet host address by combining the network number net with the local-address-within-network number local.

uint32_t function>inet_lnaof/function> (struct in_addr addr) This function returns the local-address-within-network part of the Internet host address addr.

The function works only with traditional IPv4 class A, B and C network types. It doesn't work with classless addresses and shouldn't be used anymore.

uint32_t function>inet_netof/function> (struct in_addr addr) This function returns the network number part of the Internet host address addr.

The function works only with traditional IPv4 class A, B and C network types. It doesn't work with classless addresses and shouldn't be used anymore.

int function>inet_pton/function> (int af, const char *cp, void *buf) This function converts an Internet address (either IPv4 or IPv6) from presentation (textual) to network (binary) format. af should be either AF_INET or AF_INET6, as appropriate for the type of address being converted. cp is a pointer to the input string, and buf is a pointer to a buffer for the result. It is the caller's responsibility to make sure the buffer is large enough.

const char * function>inet_ntop/function> (int af, const void *cp, char *buf, size_t len) This function converts an Internet address (either IPv4 or IPv6) from network (binary) to presentation (textual) form. af should be either AF_INET or AF_INET6, as appropriate. cp is a pointer to the address to be converted. buf should be a pointer to a buffer to hold the result, and len is the length of this buffer. The return value from the function will be this buffer address.

Host Names

Besides the standard numbers-and-dots notation for Internet addresses, you can also refer to a host by a symbolic name. The advantage of a symbolic name is that it is usually easier to remember. For example, the machine with Internet address 158.121.106.19 is also known as alpha.gnu.org; and other machines in the gnu.org domain can refer to it simply as alpha.

Internally, the system uses a database to keep track of the mapping between host names and host numbers. This database is usually either the file /etc/hosts or an equivalent provided by a name server. The functions and other symbols for accessing this database are declared in netdb.h. They are BSD features, defined unconditionally if you include netdb.h.

function>struct hostent/function> This data type is used to represent an entry in the hosts database. It has the following members:

char *h_name

This is the "official" name of the host.

char **h_aliases

These are alternative names for the host, represented as a null-terminated vector of strings.

int h_addrtype

This is the host address type; in practice, its value is always either AF_INET or AF_INET6, with the latter being used for IPv6 hosts. In principle other kinds of addresses could be represented in the database as well as Internet addresses; if this were done, you might find a value in this field other than AF_INET or AF_INET6. the section called “Socket Addresses”.

int h_length

This is the length, in bytes, of each address.

char **h_addr_list

This is the vector of addresses for the host. (Recall that the host might be connected to multiple networks and have different addresses on each one.) The vector is terminated by a null pointer.

char *h_addr

This is a synonym for h_addr_list[0]; in other words, it is the first host address.

As far as the host database is concerned, each address is just a block of memory h_length bytes long. But in other contexts there is an implicit assumption that you can convert IPv4 addresses to a struct in_addr or an uint32_t. Host addresses in a struct hostent structure are always given in network byte order; see the section called “Byte Order Conversion”.

You can use gethostbyname, gethostbyname2 or gethostbyaddr to search the hosts database for information about a particular host. The information is returned in a statically-allocated structure; you must copy the information if you need to save it across calls. You can also use getaddrinfo and getnameinfo to obtain this information.

struct hostent * function>gethostbyname/function> (const char *name) The gethostbyname function returns information about the host named name. If the lookup fails, it returns a null pointer.

struct hostent * function>gethostbyname2/function> (const char *name, int af) The gethostbyname2 function is like gethostbyname, but allows the caller to specify the desired address family (e.g. AF_INET or AF_INET6) of the result.

struct hostent * function>gethostbyaddr/function> (const char *addr, size_t length, int format) The gethostbyaddr function returns information about the host with Internet address addr. The parameter addr is not really a pointer to char - it can be a pointer to an IPv4 or an IPv6 address. The length argument is the size (in bytes) of the address at addr. format specifies the address format; for an IPv4 Internet address, specify a value of AF_INET; for an IPv6 Internet address, use AF_INET6.

If the lookup fails, gethostbyaddr returns a null pointer.

If the name lookup by gethostbyname or gethostbyaddr fails, you can find out the reason by looking at the value of the variable h_errno. (It would be cleaner design for these functions to set errno, but use of h_errno is compatible with other systems.)

Here are the error codes that you may find in h_errno:

HOST_NOT_FOUND

No such host is known in the database.

TRY_AGAIN

This condition happens when the name server could not be contacted. If you try again later, you may succeed then.

NO_RECOVERY

A non-recoverable error occurred.

NO_ADDRESS

The host database contains an entry for the name, but it doesn't have an associated Internet address.

The lookup functions above all have one in common: they are not reentrant and therefore unusable in multi-threaded applications. Therefore provides the GNU C library a new set of functions which can be used in this context.

int function>gethostbyname_r/function> (const char *restrict name, struct hostent *restrict result_buf, char *restrict buf, size_t buflen, struct hostent **restrict result, int *restrict h_errnop) The gethostbyname_r function returns information about the host named name. The caller must pass a pointer to an object of type struct hostent in the result_buf parameter. In addition the function may need extra buffer space and the caller must pass an pointer and the size of the buffer in the buf and buflen parameters.

A pointer to the buffer, in which the result is stored, is available in *result after the function call successfully returned. If an error occurs or if no entry is found, the pointer *result is a null pointer. Success is signalled by a zero return value. If the function failed the return value is an error number. In addition to the errors defined for gethostbyname it can also be ERANGE. In this case the call should be repeated with a larger buffer. Additional error information is not stored in the global variable h_errno but instead in the object pointed to by h_errnop.

Here's a small example:

struct hostent *
gethostname (char *host)
{
  struct hostent hostbuf, *hp;
  size_t hstbuflen;
  char *tmphstbuf;
  int res;
  int herr;

  hstbuflen = 1024;
  /* Allocate buffer, remember to free it to avoid memory leakage.  */
  tmphstbuf = malloc (hstbuflen);

  while ((res = gethostbyname_r (host, hostbuf, tmphstbuf, hstbuflen,
                                 hp, herr)) == ERANGE)
    {
      /* Enlarge the buffer.  */
      hstbuflen *= 2;
      tmphstbuf = realloc (tmphstbuf, hstbuflen);
    }
  /*  Check for errors.  */
  if (res || hp == NULL)
    return NULL;
  return hp;
}

int function>gethostbyname2_r/function> (const char *name, int af, struct hostent *restrict result_buf, char *restrict buf, size_t buflen, struct hostent **restrict result, int *restrict h_errnop) The gethostbyname2_r function is like gethostbyname_r, but allows the caller to specify the desired address family (e.g. AF_INET or AF_INET6) for the result.

int function>gethostbyaddr_r/function> (const char *addr, size_t length, int format, struct hostent *restrict result_buf, char *restrict buf, size_t buflen, struct hostent **restrict result, int *restrict h_errnop) The gethostbyaddr_r function returns information about the host with Internet address addr. The parameter addr is not really a pointer to char - it can be a pointer to an IPv4 or an IPv6 address. The length argument is the size (in bytes) of the address at addr. format specifies the address format; for an IPv4 Internet address, specify a value of AF_INET; for an IPv6 Internet address, use AF_INET6.

Similar to the gethostbyname_r function, the caller must provide buffers for the result and memory used internally. In case of success the function returns zero. Otherwise the value is an error number where ERANGE has the special meaning that the caller-provided buffer is too small.

You can also scan the entire hosts database one entry at a time using sethostent, gethostent and endhostent. Be careful when using these functions because they are not reentrant.

void function>sethostent/function> (int stayopen) This function opens the hosts database to begin scanning it. You can then call gethostent to read the entries.

If the stayopen argument is nonzero, this sets a flag so that subsequent calls to gethostbyname or gethostbyaddr will not close the database (as they usually would). This makes for more efficiency if you call those functions several times, by avoiding reopening the database for each call.

struct hostent * function>gethostent/function> (void) This function returns the next entry in the hosts database. It returns a null pointer if there are no more entries.

void function>endhostent/function> (void) This function closes the hosts database.

Internet Ports

A socket address in the Internet namespace consists of a machine's Internet address plus a port number which distinguishes the sockets on a given machine (for a given protocol). Port numbers range from 0 to 65,535.

Port numbers less than IPPORT_RESERVED are reserved for standard servers, such as finger and telnet. There is a database that keeps track of these, and you can use the getservbyname function to map a service name onto a port number; see the section called “The Services Database”.

If you write a server that is not one of the standard ones defined in the database, you must choose a port number for it. Use a number greater than IPPORT_USERRESERVED; such numbers are reserved for servers and won't ever be generated automatically by the system. Avoiding conflicts with servers being run by other users is up to you.

When you use a socket without specifying its address, the system generates a port number for it. This number is between IPPORT_RESERVED and IPPORT_USERRESERVED.

On the Internet, it is actually legitimate to have two different sockets with the same port number, as long as they never both try to communicate with the same socket address (host address plus port number). You shouldn't duplicate a port number except in special circumstances where a higher-level protocol requires it. Normally, the system won't let you do it; bind normally insists on distinct port numbers. To reuse a port number, you must set the socket option SO_REUSEADDR. the section called “Socket-Level Options”.

These macros are defined in the header file netinet/in.h.

int function>IPPORT_RESERVED/function> Port numbers less than IPPORT_RESERVED are reserved for superuser use.

int function>IPPORT_USERRESERVED/function> Port numbers greater than or equal to IPPORT_USERRESERVED are reserved for explicit use; they will never be allocated automatically.

The Services Database

The database that keeps track of "well-known" services is usually either the file /etc/services or an equivalent from a name server. You can use these utilities, declared in netdb.h, to access the services database. function>struct servent/function> This data type holds information about entries from the services database. It has the following members:

char *s_name

This is the "official" name of the service.

char **s_aliases

These are alternate names for the service, represented as an array of strings. A null pointer terminates the array.

int s_port

This is the port number for the service. Port numbers are given in network byte order; see the section called “Byte Order Conversion”.

char *s_proto

This is the name of the protocol to use with this service. the section called “Protocols Database”.

To get information about a particular service, use the getservbyname or getservbyport functions. The information is returned in a statically-allocated structure; you must copy the information if you need to save it across calls.

struct servent * function>getservbyname/function> (const char *name, const char *proto) The getservbyname function returns information about the service named name using protocol proto. If it can't find such a service, it returns a null pointer.

This function is useful for servers as well as for clients; servers use it to determine which port they should listen on (the section called “Listening for Connections”).

struct servent * function>getservbyport/function> (int port, const char *proto) The getservbyport function returns information about the service at port port using protocol proto. If it can't find such a service, it returns a null pointer.

You can also scan the services database using setservent, getservent and endservent. Be careful when using these functions because they are not reentrant.

void function>setservent/function> (int stayopen) This function opens the services database to begin scanning it.

If the stayopen argument is nonzero, this sets a flag so that subsequent calls to getservbyname or getservbyport will not close the database (as they usually would). This makes for more efficiency if you call those functions several times, by avoiding reopening the database for each call.

struct servent * function>getservent/function> (void) This function returns the next entry in the services database. If there are no more entries, it returns a null pointer.

void function>endservent/function> (void) This function closes the services database.

Byte Order Conversion

Different kinds of computers use different conventions for the ordering of bytes within a word. Some computers put the most significant byte within a word first (this is called "big-endian" order), and others put it last ("little-endian" order).

So that machines with different byte order conventions can communicate, the Internet protocols specify a canonical byte order convention for data transmitted over the network. This is known as network byte order.

When establishing an Internet socket connection, you must make sure that the data in the sin_port and sin_addr members of the sockaddr_in structure are represented in network byte order. If you are encoding integer data in the messages sent through the socket, you should convert this to network byte order too. If you don't do this, your program may fail when running on or talking to other kinds of machines.

If you use getservbyname and gethostbyname or inet_addr to get the port number and host address, the values are already in network byte order, and you can copy them directly into the sockaddr_in structure.

Otherwise, you have to convert the values explicitly. Use htons and ntohs to convert values for the sin_port member. Use htonl and ntohl to convert IPv4 addresses for the sin_addr member. (Remember, struct in_addr is equivalent to uint32_t.) These functions are declared in netinet/in.h. uint16_t function>htons/function> (uint16_t hostshort) This function converts the uint16_t integer hostshort from host byte order to network byte order.

uint16_t function>ntohs/function> (uint16_t netshort) This function converts the uint16_t integer netshort from network byte order to host byte order.

uint32_t function>htonl/function> (uint32_t hostlong) This function converts the uint32_t integer hostlong from host byte order to network byte order.

This is used for IPv4 Internet addresses.

uint32_t function>ntohl/function> (uint32_t netlong) This function converts the uint32_t integer netlong from network byte order to host byte order.

This is used for IPv4 Internet addresses.

Protocols Database

The communications protocol used with a socket controls low-level details of how data are exchanged. For example, the protocol implements things like checksums to detect errors in transmissions, and routing instructions for messages. Normal user programs have little reason to mess with these details directly.

The default communications protocol for the Internet namespace depends on the communication style. For stream communication, the default is TCP ("transmission control protocol"). For datagram communication, the default is UDP ("user datagram protocol"). For reliable datagram communication, the default is RDP ("reliable datagram protocol"). You should nearly always use the default.

Internet protocols are generally specified by a name instead of a number. The network protocols that a host knows about are stored in a database. This is usually either derived from the file /etc/protocols, or it may be an equivalent provided by a name server. You look up the protocol number associated with a named protocol in the database using the getprotobyname function.

Here are detailed descriptions of the utilities for accessing the protocols database. These are declared in netdb.h. function>struct protoent/function> This data type is used to represent entries in the network protocols database. It has the following members:

char *p_name

This is the official name of the protocol.

char **p_aliases

These are alternate names for the protocol, specified as an array of strings. The last element of the array is a null pointer.

int p_proto

This is the protocol number (in host byte order); use this member as the protocol argument to socket.

You can use getprotobyname and getprotobynumber to search the protocols database for a specific protocol. The information is returned in a statically-allocated structure; you must copy the information if you need to save it across calls.

struct protoent * function>getprotobyname/function> (const char *name) The getprotobyname function returns information about the network protocol named name. If there is no such protocol, it returns a null pointer.

struct protoent * function>getprotobynumber/function> (int protocol) The getprotobynumber function returns information about the network protocol with number protocol. If there is no such protocol, it returns a null pointer.

You can also scan the whole protocols database one protocol at a time by using setprotoent, getprotoent and endprotoent. Be careful when using these functions because they are not reentrant.

void function>setprotoent/function> (int stayopen) This function opens the protocols database to begin scanning it.

If the stayopen argument is nonzero, this sets a flag so that subsequent calls to getprotobyname or getprotobynumber will not close the database (as they usually would). This makes for more efficiency if you call those functions several times, by avoiding reopening the database for each call.

struct protoent * function>getprotoent/function> (void) This function returns the next entry in the protocols database. It returns a null pointer if there are no more entries.

void function>endprotoent/function> (void) This function closes the protocols database.

Internet Socket Example

Here is an example showing how to create and name a socket in the Internet namespace. The newly created socket exists on the machine that the program is running on. Rather than finding and using the machine's Internet address, this example specifies INADDR_ANY as the host address; the system replaces that with the machine's actual address.

#include stdio.h
#include stdlib.h
#include sys/socket.h
#include netinet/in.h

int
make_socket (uint16_t port)
{
  int sock;
  struct sockaddr_in name;

  /* Create the socket. */
  sock = socket (PF_INET, SOCK_STREAM, 0);
  if (sock  0)
    {
      perror ("socket");
      exit (EXIT_FAILURE);
    }

  /* Give the socket a name. */
  name.sin_family = AF_INET;
  name.sin_port = htons (port);
  name.sin_addr.s_addr = htonl (INADDR_ANY);
  if (bind (sock, (struct sockaddr *) name, sizeof (name))  0)
    {
      perror ("bind");
      exit (EXIT_FAILURE);
    }

  return sock;
}

Here is another example, showing how you can fill in a sockaddr_in structure, given a host name string and a port number:

#include stdio.h
#include stdlib.h
#include sys/socket.h
#include netinet/in.h
#include netdb.h

void
init_sockaddr (struct sockaddr_in *name,
               const char *hostname,
               uint16_t port)
{
  struct hostent *hostinfo;

  name-sin_family = AF_INET;
  name-sin_port = htons (port);
  hostinfo = gethostbyname (hostname);
  if (hostinfo == NULL)
    {
      fprintf (stderr, "Unknown host %s.\n", hostname);
      exit (EXIT_FAILURE);
    }
  name-sin_addr = *(struct in_addr *) hostinfo-h_addr;
}