Docstoc

chapter3

Document Sample
chapter3 Powered By Docstoc
					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
   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

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:2
posted:2/14/2012
language:
pages:23