Date post: | 21-Dec-2015 |
Category: |
Documents |
View: | 228 times |
Download: | 7 times |
Unix Network ProgrammingUnix Network ProgrammingPart 2: Elementary SocketsPart 2: Elementary Sockets
8.5.2005 Jani Peusaari
ContentsContents
Socket address structuresByte Ordering & ManipulationStreams
Necessary information on how to create a socket and how they work. Protocol dependency issues and introduction to performance.
NotesNotes
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 structuresSocket 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_INETin_port_t sin_port;struct in_addr sin_addr;char sin_zero
};
Structure differencesStructure 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
TypesTypes
POSIX defines different variable types that are used to define structures, to make architecture independent representations
Integer format: <signed?>int<bits>_te.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 SupportDifferent 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 IPv6From 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 alignedNew 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_INET6in_port_t sin6_port;uint32_t sin6_flowinfo;struct in6_addr sin6_addr;uint32_t sin6_scope_id;
};
New Generic Socket Address New Generic Socket Address StructureStructure
The old one only 16 bytes longNew one is defined to be as long as the
largest possible structure in the systemSupport for alignment requirements
If things were designed now, all would be cast as (void *), length field would be a requirement...
Value-Result ArgumentsValue-Result Arguments
Socket Address Structures are commonly passed as a reference
Some arguments used in two waysE.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 OrderingByte Ordering
Systems use different byte orders, known as little-endian and big-endian
Network byte order, host byte orderNetwork byte order is big-endianPOSIX requires that certain fields in socket
address structures must be maintained in network byte order
User is responsible for this
Byte ordering functionsByte 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 conversionAddress/ASCII conversion
Functions that convert from/to ASCII strings to/from network byte ordered binary valuesE.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);
ProblemsProblems
Older functions only work with IPv4, and have some special qualities
E.g. what inet_addr returns on errorNewer functions require that we know the
address family– Family as argument– Structure member names
StreamsStreams
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 presentedSolutions 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 functionsSupporting functions
Functions that operate on multibyte data, without interpreting the data, without assuming null terminates the data
4.2BSD (b*) and ANSI C (mem*) functionsNeeded 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 codePortable 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