Académique Documents
Professionnel Documents
Culture Documents
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
/* 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>
Some struct defs have a sin_len IPv4 address and TCP or UDP port number are always stored in network byte order (discussed later)
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. */ };
Socket functions are then defined as taking a pointer to the generic socket address structure:
int bind(int, struct sockaddr *, socklen_t);
*/
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)
intro/byteorder.c
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:
# 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
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);
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.
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
All that is required is for caller to invoke the read or write function again