Showing posts with label Socket. Show all posts
Showing posts with label Socket. Show all posts

Tuesday, April 26, 2011

Socket Programming in C (3): Socket to Address structure Translation

// Get address structure by sock on current side, E.g. you want to know the client port number which randomly assigned
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

// Get address structure by sock on the other side. E.g. server wants to know client's structure.
int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

Socket Programming in C (2): IP address/Hostname Translation

****************************************************************************
//Convert IP addresses from a dots-and-number string to a struct in_addr and back
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

(1) Old way, not support IPv6

char *inet_ntoa(struct in_addr in); // convert binary in network to string
int inet_aton(const char *cp, struct in_addr *inp); // convert dot-number string cp to struct in_addr pointer inp
in_addr_t inet_addr(const char *cp); // convert do-number string cp to in_addr_t

// ntoa: network to ASCII (readable)
// aton: ASCII to network
// atoi: ASCII to integer

(2) Use inet_pton() or inet_ntop(), support for IPv6 
#include <arpa/inet.h>
 

int inet_pton(int af, const char *src, void *dst); // convert string src to network dst. if af is AF_INET(IPv4), dst must be struct addr_in* type.
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); //convert network src to string dst. if af is AF_INET, src pints to a struct addr_in, and dst must be at least INET_ADDRSTRLEN bytes long

*******************************************************************************
//Convert IP addresses from host name string to a struct in_addr and back

#include <netdb.h>
#include <sys/socket.h>       /* for AF_INET */
struct hostent *gethostbyname(const char *name); // convert hostname/dotIP to a host struture, which includes network addr_in
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type); // convert a network addr_in to host structure
struct hostent {
               char  *h_name;            /* full host name*/
               char **h_aliases;         /* alias list */
               int    h_addrtype;        /* host address type */
               int    h_length;           /* length of address */
               char **h_addr_list;      /* list of addresses, often use (struct addr_in*) h_addr */
}
#define h_addr h_addr_list[0]  /* often use this one, need cast to struct addr_in*  */

*******************************************************************************
Example:
/*
 * Converts ascii text to in_addr struct.
 * NULL is returned if the address can not be found.
 * */
struct in_addr *atoaddr(char *address)
{
  struct hostent *host;
  static struct in_addr saddr;

  /* First try it as aaa.bbb.ccc.ddd. */
  saddr.s_addr = inet_addr(address);
  if (saddr.s_addr != -1)
    return &saddr;

  host = gethostbyname(address);
  if (host != NULL)
    return (struct in_addr *) *host->h_addr_list;

  return NULL;
}

Socket Programming in C (1): Address Structure

// this is all the address structure.
// first one is general one, which often declares, and the cast to a specific one
// second part is for IPv4
// third part is for IPv6
// last part is a general structure to store internet address.

include <netinet/in.h>

// All pointers to socket address structures are often cast to pointers
// to this type before use in various functions and system calls:

struct sockaddr {
    unsigned short    sa_family;     // address family, AF_xxx
    char                    sa_data[14];  // 14 bytes of protocol address
};


// IPv4 AF_INET sockets:

struct sockaddr_in {
    short                 sin_family;   // e.g. AF_INET, AF_INET6
    unsigned short   sin_port;     // e.g. htons(3490)
    struct in_addr    sin_addr;     // see struct in_addr, below
    char                  sin_zero[8];  // zero this if you want to
};

struct in_addr {
    unsigned long s_addr;          // load with inet_pton()
};


// IPv6 AF_INET6 sockets:

struct sockaddr_in6 {
    u_int16_t       sin6_family;   // address family, AF_INET6
    u_int16_t       sin6_port;     // port number, Network Byte Order
    u_int32_t       sin6_flowinfo; // IPv6 flow information
    struct in6_addr sin6_addr;     // IPv6 address
    u_int32_t       sin6_scope_id; // Scope ID
};

struct in6_addr {
    unsigned char   s6_addr[16];   // load with inet_pton()
};


// General socket address holding structure, big enough to hold either
// struct sockaddr_in or struct sockaddr_in6 data:

struct sockaddr_storage {
    sa_family_t  ss_family;     // address family
    // all this is padding, implementation specific, ignore it:
    char      __ss_pad1[_SS_PAD1SIZE];
    int64_t   __ss_align;
    char      __ss_pad2[_SS_PAD2SIZE];
};