struct hostent *gethostbyname(const char *name);
struct hostent *gethostbyaddr(const char *addr, int len, int type);
struct hostent {
char *h_name; // official name of host
char **h_aliases; // NULL-terminated list of aliases
int h_addrtype; // host address type, e.g. AF_INET
int h_length; // length of address (4 for IPv4 addresses)
char **h_addr_list; // NULL-terminated list of IP addresses
}; // h_addr_list is really a struct in_addr ** when known to be IPv4 addresses
struct in_addr {
unsigned int s_addr // stored in network byte order (big endian)
};static void publishIPAddressInfo(const string& host) {
struct hostent *he = gethostbyname(host.c_str());
if (he == NULL) { // NULL return value means resolution attempt failed
cout << host << " could not be resolved to an address." << endl;
return;
}
cout << "Official name is \"" << he->h_name << "\"" << endl;
cout << "IP Addresses: " << endl;
struct in_addr **addressList = (struct in_addr **) he->h_addr_list;
while (*addressList != NULL) {
cout << "+ " << inet_ntoa(**addressList) << endl;
addressList++;
}
}
struct sockaddr_in { // IPv4 Internet-style socket address record
unsigned short sin_family; // protocol family for socket
unsigned short sin_port; // port number (in network byte order)
struct in_addr sin_addr; // IP address (in network byte order)
unsigned char sin_zero[8]; // pad to sizeof(struct sockaddr)
};
struct sockaddr_in6 { // IPv6 Internet-style socket address record
unsigned short sin6_family; // protocol family for socket
unsigned short sin6_port; // port number (in network byte order)
// more fields, total size is > sizeof(struct sockaddr_in)
};
struct sockaddr { // generic socket address record
unsigned short sa_family; // protocol family for socket
char sa_data[14]; // address data (and defines full size to be 16 bytes)
};
static const int kClientSocketError = -1;
int createClientSocket(const string& host, unsigned short port) {
struct hostent *he = gethostbyname(host.c_str());
if (he == NULL) return kClientSocketError;
int s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) return kClientSocketError;
struct sockaddr_in serverAddress;
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(port);
serverAddress.sin_addr.s_addr = ((struct in_addr *)he->h_addr)->s_addr;
if (connect(s, (struct sockaddr *) &serverAddress,
sizeof(serverAddress)) == 0) return s;
close(s);
return kClientSocketError;
}
static const int kServerSocketFailure = -1; // sentinel for no valid socket
static const int kReuseAddresses = 1; // 1 means true here
static const int kDefaultBacklog = 128; // allow 128 clients to queue up before they are "accept"ed, drop/ignore 129th
int createServerSocket(unsigned short port) {
int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket < 0) return kServerSocketFailure;
if (setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR,
&kReuseAddresses, sizeof(int)) < 0) {
close(serverSocket);
return kServerSocketFailure;
} // setsockopt used here so port becomes available even is server crashes and reboots
struct sockaddr_in serverAddress; // IPv4-style socket address
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET; // sin_family field used to self-identify sockaddr type
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(port);
if (bind(serverSocket, (struct sockaddr *) &serverAddress, sizeof(struct sockaddr_in)) == 0 &&
listen(serverSocket, kDefaultBacklog) == 0) return serverSocket;
close(serverSocket);
return kServerSocketFailure;
}