gethostbyname函式和getservbyname函式的應用

RGBMarco發表於2018-02-07

/*******************************************************************************
函式原型: struct hostent* gethostbyname(const char* name)
函式說明:通過主機名呼叫gethostbyname返回包含主機正式名稱,主機別名,IPV4地址等資訊的結構體
返回值: 若成功返回struct hostent*,出錯返回NULL,並修改全域性變數h_errno,不修改errno
**********************************************************************************/

/***********************************************************************************
struct hostent {
char* h_name;//主機正式規範名稱
char** h_aliases;//主機別名
int h_addrtype; //主機地址型別
int h_length;//地址長度
char** h_addr_list;//地址列表(IPV4)
}
***********************************************************************************/

/***********************************************************************************
函式原型: struct servent* getservbyname(const char* name,const char*protoname)
函式說明:通過服務名+使用協議(若為NULL,得到結構體採用協議依賴實現),得到包含正式服務名,服務別名,服務埠,服務使用協議等資訊的結構體
返回值:若成功,返回struct servent*,若失敗,返回NULL
***********************************************************************************/

/**********************************************************************************
struct servent {
char *s_name; //正式服務名
char** s_aliases;//服務名別名
char* s_port;//服務埠號
char* s_proto;//服務採用協議
}
**********************************************************************************/

應用:通過TCP C/S獲取時間 :
伺服器程式碼:(從別的主機獲取時要確保它們的標準時間伺服器埠已開啟):

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <errno.h>

#define PORT 13
#define LISTENQ 100

void sig_child(int signo) {
    int ppid;
    while ((ppid = waitpid(-1,NULL,WNOHANG)) < 0) {
        printf("waitpid error: %s\n",strerror(errno));
        exit(1);
    }
}

void server_echo(int fd) {
    char str[128];
    time_t t = time(NULL);
    strftime(str,sizeof(str),"%Y %x %X",localtime(&t));
    int len = strlen(str);
    str[len] = '\n';
    str[len + 1] = '\0';
    if (write(fd,str,strlen(str)) != strlen(str)) {
        printf("write error: %s\n",strerror(errno));
        exit(1);
    }
}

int main() {
    int sockfd;
    if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
        printf("socket error: %s\n",strerror(errno));
        exit(1);
    }

    struct sockaddr_in serveraddr;
    bzero(&serveraddr,sizeof(struct sockaddr_in));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(PORT);
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(struct sockaddr_in)) < 0) {
        printf("bind error: %s\n",strerror(errno));
        exit(1);
    }

    if (listen(sockfd,LISTENQ) < 0) {
        printf("listen error: %s\n",strerror(errno));
        exit(1);
    }

    if (signal(SIGCHLD,sig_child) == SIG_ERR) {
        printf("signal error: %s\n",strerror(errno));
        exit(1);
    }
    int connfd;
    int pid;
    for (; ;) {
        if ((connfd = accept(sockfd,NULL,NULL)) < 0) {
            if (errno == EINTR) {
                continue;
            }
            printf("accept error: %s\n",strerror(errno));
        }
        if ((pid = fork()) < 0) {
            printf("fork error: %s\n",strerror(errno));
            exit(1);
        }else if (pid == 0) {
            close(sockfd);
            server_echo(connfd);
            close(connfd);
            exit(0);
        }
        close(connfd);
    }
    return 0;
}

客戶端程式碼:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>

#define BUFSIZE 4096

int main(int argc,char **argv) {
    if (argc != 3) {
        printf("add <hostname> <serveices>\n");
        exit(1);
    }

    struct hostent* host;
    struct in_addr** ppaddr;
    struct in_addr* addr[2];
    struct in_addr initaddr;
    if ((host = gethostbyname(argv[1])) == NULL) {
        if (inet_pton(AF_INET,argv[1],&initaddr) <= 0) {
            printf("gethostbyname error: %s\n",hstrerror(h_errno));
            exit(1);
        }else {
            addr[0] = &initaddr;
            addr[1] = NULL;
            ppaddr = addr;
        }
    }else {
        ppaddr = (struct in_addr**)host->h_addr_list;
    }

    struct servent* service;
    if ((service = getservbyname(argv[2],NULL)) == NULL) {
        printf("getservbyname error\n");
        exit(1);
    }
    int sockfd;
    struct sockaddr_in serveraddr;
    bzero(&serveraddr,sizeof(struct sockaddr_in));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = service->s_port;
    for (; *ppaddr != NULL; ++ppaddr) {
        if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
            printf("socket error: %s\n",strerror(errno));
            exit(1);
        }
        memcpy(&serveraddr.sin_addr,*ppaddr,sizeof(struct in_addr));
        char str[INET_ADDRSTRLEN];
        if (inet_ntop(AF_INET,&serveraddr.sin_addr,str,sizeof(str)) == NULL) {
            printf("inet_ntop error: %s\n",strerror(errno));
            exit(1);
        }
        printf("trying to connect IP: %s  port: %d\n",str,ntohs(serveraddr.sin_port));
        if (connect(sockfd,(struct sockaddr*)&serveraddr,sizeof(struct sockaddr_in)) == 0) {
            printf("connect to IP: %s port success: %d\n",str,ntohs(serveraddr.sin_port));
            break;
        }
        printf("connect to IP: %s port: %d failed reason: %s\n",str,ntohs(serveraddr.sin_port),strerror(errno));
    }
    if (*ppaddr == NULL) {
        printf("all connect failed\n");
    }

    char recv[BUFSIZE];
    int n;
    while ((n = read(sockfd,recv,BUFSIZE)) > 0) {
        if (write(STDOUT_FILENO,recv,n) != n) {
            printf("write error: %s\n",strerror(errno));
            exit(1);
        }
    }
    return 0;
}

執行:

這裡寫圖片描述

相關文章