184 Network Programming and Design
IPv4 IPv6 Unix Datalink
sockaddr_in ( ) sockaddr_in6( ) sockaddr_un ( ) sockaddr_d1 ( ) length' AF_INET
16-bit port#
32-bit IPv4 address
(unused)
fixed length (16bytes)
length AF_INET6 16-bit port#
32-bit flow label
IPv6 address 128-bit
fixed length (24 bytes)
lengthl AF_LOCAL
path ame (up to 104 bytes)
variable length
length I AF_LINK interface index
type name len addr len sel len
interface name and link-layer address
variable length
Figure 1.5 Comparison of various socket address structures
Socket Introduction 185
user process
n t l e n g t h s o c k e t address structure
protoco addres kernel
Figure 1.6 Socket address structure passed from process to kernel.
We
will see in the next unit that the datatype for the size of a socket address structure is actually socklen_t and not int, but Posix.lg recommends that socklett defined as ui nt 32_t.
2. The four functions accept, reufrom, getsockname, and getpeerbame pass a socket address structure from the kernel to the process, the reverse direction from the previous scenario. Two of the argu-ments to these four functions are the pointer to an integer containing the size of the structure, as in.
struct sockaddr_un cli ; / * Unix domain * /
socklen_t len
len = sizeof (cli) ; / * len is a value
getpeername (unixfd, (SA* ) &cli, &len ) / * len may have changed * /
The reason that the size changes from an integer to be a pointer to an integer is because the size is both a
value
when the function is called (it tells the kernel the size of the structure, so that the kernel does not write past the end of the structure when filling it in) and a
resultwhen the function returns (it tells the process how much information the kernel actually stored in the structure). This type of argument is called a
value-result
argument. Figure 1.7 shows this scenario.
user process socket address
protoco address
kernel v•
*
Figure 1.7 Socket address structure passed from kernel to process.
186 Network Programming and Design
When using value-result arguments for the length of socket address structures, if the socket address structure is fixed length (Figure 1.5), the value returned by the kernel will always be that fixed size: 16 for an IPv4 sockaddr_in and 24 for an IPv6 sockaddr_i n6, for example. But with a variable-length socket address structure (e.g., a Unix domain sockaddr_un the value returned can be less than the maximum size of the structure.
With network programming the most common example of a value-result argument is the length of a returned socket address structure. But we will encounter other value -result arguments in this text:
The middle three arguments for the select function
The length arguments for the getsockopt function.
The msgnamelen and msg_controllen members of the m sgh d r structure, when used with recvmsg .
The ifc_len member of the ifconf structure.
The first of the two length arguments for the sysctl function.
3.3 Byte Ordering Function
Consider a 16-bit integer that is made up of 2 bytes. There are two ways to store the 2 bytes in memory: with the low-order byte at the starting address, known as little-endian byte order, or with the high-order byte at the starting address, known as big-endian byte order. We show these two formats in Figure 1.8.
4 ___________________________________ increasing memory addresses
addresses A+1 addresses A
little-endian byte order: high-order byte low-order byte
Jr Jr
MSB 16-bit value LSB
b g-endian byte order: high-order byte low-order byte
addresses A addresses A+1
4 increasing memory addresses
Figure 1.8 Little-endian byte order and big-endian byte order for a 16-bit integer
In this figure we show increasing memory addresses going from right to left in the top, and from left to right in the bottom. We also show the MSB (most significant bit) as the leftmost bit of the 16-bit value and the LSB
(least significant bit) as the rightmost bit.
Unfortunately there is no standard between these two byte orderings and we encounter systems that use both formats. We refer to the byte ordering used by a given system as the host byte order The program shown in Figure 1.9 prints the host byte order.
Socket Introduction 187 intro/byteorder c
1# include"unp.h"
2 int
3 main ( int argc, char *"argv) 4 (
5 union (
6 short s;
7 char c[sizeof (short)];
8 } un ;
9 un.s = 0x0102 ;
10 printf ("%s:" CPU_VENDOR_OS);
11 if (sizeof (short)== 2) {
if (un .c[0]= = 1 && un.c[1] = = 2) 13 printf ("big-endian \ n");
14 else if (un.c[0] = = 2 && un .c [1] = = 1) 15 printf ( "little-endian \ n");
16 else
17 printf ( "unknown \ n" );
18 } else
19 printf ( "sizeof (short) -= %cl \ n", sizeof (short));
20 exit (0);
21 }
____________________________________________________________________ intro/byteorderc Figure 1.9 Program to determine host byte order.
We store the 2-byte value Ox0102 into the short integer and then look at the two consecutive bytes c(10) (the address A in Figure 1.8) and 41] (the address A+1 in Figure 1.8) to determine the byte order.
The string CP U_VE N DO R_OS is determined by the GNU a utoconf program when the software in this book is configured, and it identifies the CPU type, vendor, and operating system release. We show some exaples here in the output from this program when run on the various systems in Figure 1.7 in Unit 2.
aix% b y t e o r d e r
p o w e r p c • i b m - a i x 4 2 0 0 b g e n d a n
a l p h a % b y t e o r d e r a l p h a • d e c -o s f 4 . 0 l i t t l e . e n d i a n
bsdi%byteorder i386-pcbsdi3.0:little-endian gemini%byteorder sparc.sun-sunos4.1.4:big-endian hpux%bytearder hppal.1-hp-hpux10.30:big-endian
188 Network Programming and Design
I nux%byteorder 1586-pc-linux-gnutittle-endian
solans%byteorder sparc-sun-solans2 5 1:big-endian
unixware%byteorder 1386-univel-sysv4 2MPhttle-endian
We have talked about the byte ordering of a 16-bit integer, and obviously the same discussion applies to a 32-bit integer.
We must deal with the byte ordering differences as network programmers because networking protocols must specify a network byte order For example, in a TCP segment there is a 16-bit port number and a 32- bit IPv4 address. The sending protocol stack and the receiving protocol stack must agree on the order in which the bytes of these multi-byte fields are transmitted. The Internet protocols use big-endian byte order-ing for these multibyte integers.
In theory an implementation could store the fields in a socket address structure in host byte order and convert to and from the network byte order when moving the fields to and from the protocol headers, saving us from having to worry about this detail. But both history and Posix.Ig specify that certain fields in the socket address structures be maintained in network byte order. Our concern is therefore converting between the host byte order and the network byte order. We use the following four functions to convert between these two byte orders.
#include <netinet/in.h>
uint16_t htons(uint16_t host 1 6bitvalue);
uint32_t htonl(uint32_t host32bitvalue);
Both return: value in network byte order
uint 1 6_t ntohs(ui nt 1 6_t netbsbitvaue);
uint32_t ntohl(uint32_t n e t3 2 b i tv a lu e );
Both return: value in host byte order
In the names of these functions h stands for host, n stands for network, s stands for short, and / stands for long. The terms shot and long\are historical artifacts from the Digital VAX implementation of 4.2BSD.
We should instead think of s as a 16-bit value (such as a TCP or UDP port number) and / as a 32-bit value (such as an IPv4 address). Indeed, on the 64-bit Digital Alpha, a long integer occupies 64 bits, yet the htonl and ntoh I functions operate on 32-bit values.
When using these functions we do not care about the actual values (big endian or little endian) for the host byte order and the network byte order. What we must do is be certain to call the appropriate function to convert a given value between the host and network byte order. On those systems that have the same byte ordering as the Internet protocols (big endian), these four functions are usually defined as null macros.
4.0
Condusiun
In this unit, you have learned about the sockets application program interface and sockets address stale-tures. You also learned about the address conversion functions between a text representation of an address and the binary value.
Socket Introduction 189
11$0" 1:$0,1000,11
What you have learned in this unit borders on sockets application program interface and the sockets address structures. You also learned about the address conversion. What you will learn in the next few units will build upon this issues.
6.0 Thtor Marked Assignment.
a) Describe the structure of the IPv4 socket address structure Exercise 1.1
Describe the structures of a socket address.
Exercise 1.2
Write on Byte ordering functions
etentes and Oth
er: esoureetc•.:Stevens, W.R. Unix Network Programming. (2nd ed.) Vol. 1, Prentice Hall, PTR, 1998.
Module 3: Overview of Network Programming
o!rnanitS
Page
1.0 Introduction ... 191
2.0 Objectives ... 191
3.0 Preamble ... 191
3.1 TCP Echo Server:
main
function ... 1923.2 TCP Echo Server:
str_echo
function ... 1933.3 TCP Echo Client:
main
Function ... 1933.4 TCP Echo Client:
str_cli
function ... 1943.5 Normal Startup ... 194
3.6 Normal Termination ... 196
3.7 Posix Signal Handling ... 197
4.0 Conclusion ... 200
5.0 Summary ... 200
6.0 Tutor Marked Assignment ... 200
7.0 References and other Resources ... 200
190
TCP Client and Server Example 191
1.0 Introduction
In
this unit, you will learn about the use of elementary functons and how they can be used to wirte a complete TCP client-server example. You will also learn how to perform simple I-0 operations between a server and a client. Let us now see what you will learn in this unit as stated in the unit objectives below.
24
ObjectivesBy the end of this unit, you should be able to:
perform a read operation from a standard input and writes the line to the server.
read a line from a network input and echo the line back to the client
read and echoed line from the client and print it on its standard output.
We now use the elementary functions from the previous chapter to write a complete TCP client-server
example Our simple example is an echo server that performs the following steps:1 The client reads a line to text from its etmielarcl input and writes the line to the server.
2 The server reads the line from its network input and echoes
the line back to the client 3. The client reads the echoed line and prints it on its standard output.
Figure 1.1 depicts this simple client-server along with the functions used for input and output.
stdin tgets
stdout !puts
p.
TCP client
writen i
readline writ en
TCP
re
adline
server
Figure 1.1 Simple echo client and server