linuxnetwork-programmingubuntu-10.04

How getservbyname can get the server port information if it is run on a client machine?


The following client program trys to connect to a server and finds the current time and date on that server.

/*  Start with the usual includes and declarations.  */

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    char *host;
    int sockfd;
    int len, result;
    struct sockaddr_in address;
    struct hostent *hostinfo;
    struct servent *servinfo;
    char buffer[128];

    if(argc == 1)
        host = "localhost";
    else
        host = argv[1];

/*  Find the host address and report an error if none is found.  */

    hostinfo = gethostbyname(host);
    if(!hostinfo) {
        fprintf(stderr, "no host: %s\n", host);
        exit(1);
    }

/*  Check that the daytime service exists on the host.  */

    servinfo = getservbyname("daytime", "tcp");
    if(!servinfo) {
        fprintf(stderr,"no daytime service\n");
        exit(1);
    }
    printf("daytime port is %d\n", ntohs(servinfo -> s_port));

/*  Create a socket.  */

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

/*  Construct the address for use with connect...  */

    address.sin_family = AF_INET;
    address.sin_port = servinfo -> s_port;
    address.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list;
    len = sizeof(address);

/*  ...then connect and get the information.  */

    result = connect(sockfd, (struct sockaddr *)&address, len);
    if(result == -1) {
        perror("oops: getdate");
        exit(1);
    }

    result = read(sockfd, buffer, sizeof(buffer));
    buffer[result] = '\0';
    printf("read %d bytes: %s", result, buffer);

    close(sockfd);
    exit(0);
}

Question:

We run the above program on a client machine, how the function getservbyname can get the server information without a reference to the server machine in the parameter list?


Solution

  • getservbyname simply looks in /etc/services to find the "daytime" service using the "tcp" protocol.

    It's just a convenience, to save you from parsing that file.

    Edit (clarification)

    Each of these protocols has a friendly name ("daytime", "http", etc) and a useful name (the port number - 13, 80 etc). /etc/services holds this mapping, nothing more.