Hostname and IP Address

So for, we have assumed that both the server and client run on the same computer using localhost or IP= 127.0.0.1, and the server uses a fixed port number. If the reader intends to run the server and client on different hosts with a server port number assigned by the OS kernel, it is necessary to know server’s host name or IP address and its port number. If a computer runs TCP/IP, its hostname is usually recorded in the /etc/hosts file. The library function

gethostname(char *name, sizeof(name))

returns the machine’s hostname string in a name array, but it may not be the full official name in dot notation, nor its IP address. The library function

struct hostent *gethostbyname(void *addr, socklen_t len, int typo)

can be used to get the full name of the machine, as well as its IP address. It returns a pointer to a hostent structure in <netdb.h>, which is

Note that h_addr is defined as a char *, but it points at a 4-byte IP address in network byte order. The contents of h_addr can be accessed as

u32 NIP = *(u32 *)h_addr is the host IP address in network byte order.

u32 HIP = ntohl(NIP) is NIP in host byte order.

inet_ntoa(NIP) converts NIP to a string in DOT notation.

The following code segments show how to use gethostbyname() and getsockname() to get the server IP address and port number if it is dynamically assigned. The server must publish its hostname or IP address and port number for clients to connect.

/********* TCP server code *********/

char myname[64];

struct sockaddr_in server_addr, sock_addr;

// 1. gethostname(), gethostbyname()

gethostname(myname,64);

struct hostent *hp = gethostbyname(myname);

if (hp == 0){

printf(“unknown host %s\n”, myname); exit(1);

}

// 2. initialize the server_addr structure

server_addr.sin_family = AF_INET; // for TCP/IP

server_addr.sin_addr.s_addr = *(long *)hp->h_addr;

server_addr.sin_port =0; // let kernel assign port number

// 3. create a TCP socket

int mysock = socket(AF_INET, SOCK_STREAM, 0);

// 4. bind socket with server_addr

bind(mysock,(struct sockaddr *)&server_addr, sizeof(server_addr));

// 5. get socket addr to show port number assigned by kernel

getsockname(mysock, (struct sockaddr *)&name_addr, &length);

// 6. show server host name and port number

printf(“hostname=%s IP=%s port=%d\n”, hp->h_name,

inet_ntoa(*(long *)hp->h_addr), ntohs(name_addr.sin_port));

/********* TCP client code *********/

// run as client server_name server_port

struct sockaddr_in server_addr, sock_addr;

// 1. get server IP by name

struct hostent *hp = gethostbyname(argv[1]);

SERVER_IP = *(long *)hp->h_addr;

SERVER_PORT = atoi(argv[2]);

// 2. create TCP socket

int sock = socket(AF_INET, SOCK_STREAM, 0);

// 3. fill server_addr with server IP and PORT#

server_addr.sin_family = AF_INET;

server_addr.sin_addr.s_addr = SERVER_IP;

server_addr.sin_port = htons(SERVER_PORT);

// 4. connect to server

connect(sock,(struct sockaddr *)&server_addr, sizeof(server_addr));

Incorporating hostname and IP address into the TCP server-client program is left as exercises in the problem section.

Source: Wang K.C. (2018), Systems Programming in Unix/Linux, Springer; 1st ed. 2018 edition.

Leave a Reply

Your email address will not be published. Required fields are marked *