Vous êtes sur la page 1sur 17

Introduction to Socket Details

Unix Network Programming Ch #3

Socket Address Structure

Most socket functions (Posix C lib) require a pointer to a socket address struct as an argument Each supported protocol suite defines its own socket address struct

Names begin with sockaddr_ End with a unique suffix for each protocol

IPv4 Socket Address Struct

/usr/include/netinet/in.h [#include <netinet/in.h>]


/* Internet address. */ typedef uint32_t in_addr_t; struct in_addr { in_addr_t s_addr; };

/* Structure describing an Internet socket address. */ struct sockaddr_in { __SOCKADDR_COMMON (sin_); in_port_t sin_port; /* Port number. */ struct in_addr sin_addr; /* Internet address. */ /* Pad to size of `struct sockaddr'. */ unsigned char sin_zero[sizeof (struct sockaddr) __SOCKADDR_COMMON_SIZE sizeof (in_port_t) sizeof (struct in_addr)]; };

<bits/sockaddr.h>

IPv4 Socket Address Structure


Some struct defs have a sin_len IPv4 address and TCP or UDP port number are always stored in network byte order (discussed later)

Generic Socket Address Structure

A socket address structure is always passed by reference when passed as an argument Any socket function must deal with structs from any of the supported protocol families

Therefore they require a generic struct Defined in <sys/socket.h> (actually pulled out of <bits/socket.h> on our system

/* Structure describing a generic socket address. */ struct sockaddr { __SOCKADDR_COMMON (sa_); /* Common data: address family and length. */ char sa_data[14]; /* Address data. */ };

Generic Socket Address Struct

Socket functions are then defined as taking a pointer to the generic socket address structure:
int bind(int, struct sockaddr *, socklen_t);

To call bind, for example:


struct sockaddr_in serv; /* IPv4 socket address structure */ /* fill in serv{} */ bind(sockfd, (struct sockaddr *) &serv, sizeof(serv));

IPv6 Socket Address Structure

IPv6 socket address is also defined in <netinet/in.h>:


/* IPv6 address */ struct in6_addr { union { uint8_t u6_addr8[16]; uint16_t u6_addr16[8]; uint32_t u6_addr32[4]; } in6_u; #define s6_addr in6_u.u6_addr8 #define s6_addr16 in6_u.u6_addr16 #define s6_addr32 in6_u.u6_addr32 }; /* Ditto, for IPv6. */ struct sockaddr_in6 { __SOCKADDR_COMMON (sin6_); in_port_t sin6_port; /* Transport layer port # */ uint32_t sin6_flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ uint32_t sin6_scope_id; /* IPv6 scope-id */ };

New Generic Socket Address

IPv6 defined a new generic socket address structure:


struct sockaddr_storage { __SOCKADDR_COMMON (ss_); /* Address family, etc. */ __ss_aligntype __ss_align; /* Force desired alignment. char __ss_padding[_SS_PADSIZE]; };

*/

Comparison of Socket Address Structures

Byte Ordering Functions

Consider a 16-bit integer that is made up of two bytes. There are 2 ways to store the two bytes in memory:

With the low-order byte at the starting address (little-endian) With the high-order byte at the starting address (big-endian)

Show figure 3.9, pg. 77

Program to Determine Byte Order

intro/byteorder.c

Network Byte Order

We must deal with these byte ordering differences as network programmers Networking protocols must specify a network byte order IP uses big-endian byte ordering We use the following 4 functions to convert between host and network byte ordering:

Network Byte Order


#include <netinet/in.h> uint16_t htons(uint16_t host16bitvalue); uint32_t htonl(uint32_t host32bitvalue); uint16_t ntohs(uint16_t net16bitvalue); uint32_t ntohl(uint32_t net32bitvalue);

# if __BYTE_ORDER == __BIG_ENDIAN /* The host byte order is the same as network byte order, so these functions are all just identity. */ # define ntohl(x) (x) # define ntohs(x) (x) # define htonl(x) (x) # define htons(x) (x) # else # if __BYTE_ORDER == __LITTLE_ENDIAN # define ntohl(x) __bswap_32 (x) # define ntohs(x) __bswap_16 (x) # define htonl(x) __bswap_32 (x) # define htons(x) __bswap_16 (x) # endif # endif #endif

Byte Manipulation Functions

2 groups of functions operate on multibyte fields

can't rely on C convention of null-terminated string, since data can contain zeros (e.g IP addresses)

#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); 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);

inet_aton, inet_addr and inet_ntoa

Convert internet addresses between ASCII strings and network byte ordered binary values

inet_aton, inet_ntoa and inet_addr convert an Ipv4 address from a dotted-decimal string (e.g. 206.168.112.96) to its 32-bit network byte ordered binary value Newer functions inet_pton and inet_ntop handle both IPv4 and IPv6 addresses.

Readn, writen and readline functions

Stream sockets (e.g. TCP sockets) exhibit a behavior with the read and write functions that differs from normal file I/O A read or write on a stream socket might input or output fewer bytes than requested

But this is not an error condition

All that is required is for caller to invoke the read or write function again

Vous aimerez peut-être aussi