Cleansocks provides objects and methods to support
IP version 4 (no version 6 just now).
Include
cleanip.h to get them.
TCPsocket ts;
UDPsocket us;
These declare objects representing sockets
that use the TCP and UDP protocols, respectively.
They are derived from the socket class,
so the socket operations described there can be applied to them.
IPaddress a;
IPaddress b("w.x.y.z");
IPaddress c(in_addr_t v););
These declare an IP v. 4 address object. The value can be given
as a string in dotted decimal notation
or from a 32-bit integer. (The type in_addr_t is an alias for
a 32-bit unsigned integer.)
The default constructor produces
an invalid address,
but you may want to use it to declare a variable
which you can assign later.
Use lookup_host (below) to get an
address from a host name.
This succeeds or throws an exception.
b.set("w.x.y.z");
c.set(in_addr_t v);
The set method changes which address the IPaddress holds. Plain old
assignment works fine in the second case.
in_addr_t v = c.get();
And you can extract the numeric address as well.
string s = a.str();
This will return a string representation of the address in the conventional
dotted decimal form.
IPport p;
IPport q(uint16_t v);
This class represents an IP port number. It may be constructed by
by specifying the number, or by default to assign later.
Use lookup_service (see below) to look up a port number by its service
name.
uint16_t v = q.get();
And you can get your number back.
string s = p.str();
This will return a string representation of the port, as a decimal number.
IPendpoint;
IPendpoint e(const IPaddress &a, const IPport &p);
This is the IP derivative of an endpoint, built
from an IP address and a port number.
IPaddress a = e.addr();
IPport p = e.port();
Extractors for the parts that comprise an endpoint.
string s = e.str();
This will return a string representation of the endpoint as the IP address in
dotted decimal form, followed by the port number, separated by a colon.
IPaddress a = lookup_host(string hn);
The lookup_host method takes a host name or a string
representation of an address,
and returns its
IP address. It will succeed or
throw an exception.
IPport a = lookup_service(string hn);
The lookup_service method takes the name of a standard service
and looks up the standard port number. For instance, if you look up
http you will get port 80.
IPaddress::any()
This is the so-called wild-card address. It is used to build an IPendpoint
that represents a specified port at any address.
This is used so that a server can bind to a port on any local address.
IPaddress, IPport and IPendpoint
objects may also be printed
to output streams, though stream input is not defined.
Printed values match the returns from the object's str() method.
Byte Order
Modern computer systems use byte-addressable memory, just meaning that
each byte of storage has its own memory address. This means that any
value larger than one byte, such as an integer, is actually stored
across several consecutive memory addresses. This seems simple enough,
but
it's not. You can arrange the bytes among those addresses in different
orders. This matters for networking because data is sent on a network
by copying bytes from memory onto the network connection, and placing
them into memory at the other end in the order they emerge from the
connection. This should create no problem when sending character
data, but when sending, for instance, an integer, if the two ends store
integer data in different orders, the transmitted value will be
misinterpreted at the receiver. To deal with this, the Internet
specifies an order for data to be transmitted (creatively: “network
byte order.”) Since particular platforms (notably Pentium) do not
use network byte order for numeric data, endpoints must convert numbers
to network order before sending, and convert to host order when receiving.
Of particular interest are IP address and port numbers which must be
expressed in network order. Cleansocks generally hides this detail from
you. When you store a numeric IP or port number in the relevant Cleansocks
object, they just take care of things. When all the application data is
text, such as transmitting web pages using HTTP, you don't have to give
a thought to byte order. But Cleansocks can't keep the cruel world out
forever. If have a protocol where the payloads contain numeric data,
including IP addresses or ports, the programmer must deal with it.
Here are some tools.
First, the basic conversions from the standard socket interface
are available as usual:
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
These function
stand, respectively, for Host To Net Long, Host To Net Short,
Net To Host Long and Net To Host Short. Long means 32 bits and short means 16.
They simply convert a number between network and host order. They are
installed according to whatever host you are running on, so if your
platform already uses network order, each of these functions simply
returns its argument. For others (including most PC's), it does the
needed conversion. Use the call whenever appropriate, and you won't need
to worry which your platform is, or change you code if it is compiled elsewhere.
Cleansocks objects also have some useful support calls. Below, a is
an IPaddress, and p is an IPport.
IPaddress a(uint8_t w, uint8_t x, uint8_t y, uint8_t z);
a.set(uint8_t w, uint8_t x, uint8_t y, uint8_t z);
These allow an address to be created from individual bytes, most significant
to least.
a.net(in_addr_t n)
in_addr_t n = a.net()
p.net(uint16_t n)
uint16_t n = p.net()
These calls get or set an address or port value in network order, regardless
of the host order. For instance, p.set(x) is
equivalent to
p.net(htons(x)).