230 likes | 413 Views
Unix Network Programming Part 2: Elementary Sockets. 8.5.2005 Jani Peusaari. Contents. Socket address structures Byte Ordering & Manipulation Streams Necessary information on how to create a socket and how they work. Protocol dependency issues and introduction to performance. Notes.
E N D
Unix Network ProgrammingPart 2: Elementary Sockets 8.5.2005 Jani Peusaari
Contents • Socket address structures • Byte Ordering & Manipulation • Streams • Necessary information on how to create a socket and how they work. Protocol dependency issues and introduction to performance.
Notes • In the book: • {} means a structure, e.g. in_addr{} • Solid boxes demonstrate system functions • Boxes with dashed lines demonstate authors own functions • ’const’ pointers as function arguments mean their contents are not changed in the function
Socket address structures • Socket functions work through a reference to a protocol dependent address structure (sockaddr_ + protocol suffix) • Structures are used to pass information between the process and the kernel • Structures reside only on a given host, and are not passed in actual communication
struct in_addr { in_addr_t s_addr; }; struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family; // AF_INET in_port_t sin_port; struct in_addr sin_addr; char sin_zero };
Structure differences • POSIX only requires sin_family, sin_addr and sin_port • A POSIX compliant implementation may have additional fields • Almost all have implementations have a sin_zero field so that structures are at least 16 bytes (128 bits) long
Types • POSIX defines different variable types that are used to define structures, to make architecture independent representations • Integer format: <signed?>int<bits>_t e.g. uint8_t, int16_t • For backward compatibility reasons, some structure members can be other structures, that are again typedef’d as e.g. uint32_t • Also u_char, u_long for backward reasons
Different Protocol Support • All socket functions must be usable with different protocol families • Socket address structures are of different size • Solution: Generic socket address structure • All functions require that structures are cast into a pointer to this generic structure, e.g.: bind(sockfd, (struct sockaddr *)serv, sizeof(serv)) • Kernel checks protocol family
From IPv4 to IPv6 • SIN6_LEN constant defined if sin6_len field present in socket address structure • Family is AF_INET6 (In IPv4 AF_INET) • Structure designed to be 64-bit aligned • New generic socket address structure defined: struct sockaddr_storage
struct in6_addr { uint8_t s6_addr[16]; }; struct sockaddr_in { uint8_t sin6_len; sa_family_t sin6_family; // AF_INET6 in_port_t sin6_port; uint32_t sin6_flowinfo; struct in6_addr sin6_addr; uint32_t sin6_scope_id; };
New Generic Socket Address Structure • The old one only 16 bytes long • New one is defined to be as long as the largest possible structure in the system • Support for alignment requirements • If things were designed now, all would be cast as (void *), length field would be a requirement...
Value-Result Arguments • Socket Address Structures are commonly passed as a reference • Some arguments used in two ways E.g. int accept(int s, struct sockaddr *addr, socklen_t *addrlen); • *addrlen is a value when called, result when function returns (especially for variable length socket address structures)
Byte Ordering • Systems use different byte orders, known as little-endian and big-endian • Network byte order, host byte order • Network byte order is big-endian • POSIX requires that certain fields in socket address structures must be maintained in network byte order • User is responsible for this
Byte ordering functions • Host to Network functions uint16_t htons(uint16_t host16bitvalue); uint32_t htonl(uint32_t host32bitvalue); • Network to Host functions uint16_t ntohs(uint16_t net16bitvalue); uint32_t ntohl(uint32_t net32bitvalue);
Address/ASCII conversion • Functions that convert from/to ASCII strings to/from network byte ordered binary values E.g. ”157.24.8.133” to 32-bit network byte ordered binary value • ASCII / Network (inet_aton, inet_ntoa) • Presentation / Numeric (inet_pton, inet_ntop)
#include <arpa/inet.h> int inet_aton(const char *strptr, struct in_addr *addrptr); in_addr_t inet_addr(const char *strptr); // DONT USE char *inet_ntoa(struct in_addr inaddr);
#include <arpa/inet.h> int inet_pton(int family, const char *strptr, void *addrptr); const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
Problems • Older functions only work with IPv4, and have some special qualities E.g. what inet_addr returns on error • Newer functions require that we know the address family • Family as argument • Structure member names
Streams • File reading functions, e.g. read/write are also used with stream sockets • Unlike with files, these functions may return less bytes read/written than requested, but it is not an error • The book demonstrates functions, which correctly handle stream sockets
Solutions presented • The book shows sock_* functions, an approach for family independent code • Instead of calling e.g. inet_ntop directly, call a matching sock_ntop function, which looks inside the socket address structure for family, and call inet_ntop accordingly • Approach that simplifies portability between families
Supporting functions • Functions that operate on multibyte data, without interpreting the data, without assuming null terminates the data • 4.2BSD (b*) and ANSI C (mem*) functions • Needed for zeroying socket address structures, copying structures / structure members
#include<strings.h> void bzero(void *dest, size_t nbytes); void bcopy(const void *src, void *dest, size_t nbytes); int bcmp(const void *ptr1, const void *ptr2, size_t nbytes); #include<string.h> void *memset(void *dest, int c, size_t len); void *memcpy(void *dest, const void *src, size_t nbytes); int memcmp(const void *ptr1, const void *ptr2, size_t nbytes);
Portable code • Compile time tests to check socket address structures • Always check socket address structure size (e.g. sizeof(sockaddr_in)) • Use newer inet_* functions that support both IPv4 and IPv6 addresses • Possibly with wrappers to handle address families in an independent way