网络编程学习笔记(getservbyname和getservbyport函数)

来源:互联网 发布:网络推广框架协议 编辑:程序博客网 时间:2024/05/17 03:24

通过服务器的名字而不是服务器端口号来认知它,而且如果从主机到端口号的映射包含在一个文件中(一般是/etc/services),则如果端口号改变,我们所需做的所有改动就是改动文件/etc/services中的一行,而不是重新编译应用程序。

getservbyname函数原型为:

#include <netdb.h>struct servent *getservbyname(const char *servname, const char *protoname);
成功返回非空指针,失败返回空指针

此函数返回一个指向下面所示结构的指针:

struct servent{    char *s_name;     //official service name    char **s_aliases;    // alias list    int s_port;// port number, network-byte order    char *s_proto;// protocol to use};

服务名必须指定,如果指定了一个协议(即protoname为非空指针),则结果表项也必须有匹配的协议。如果protoname没有指定且服务支持多个协议,则返回哪个端口是依赖于实现的。一般来说这没有关系,因为支持多个协议的服务常常使用相同的TCP和UDP端口号,但并没有保证

结构servent中我们关心的主要成员是端口号,由于端口号是以网络字节序返回的,在将它存储于套接口地址结构时,绝对不能调用htons

对此函数的典型调用是:

struct servent *sptr;sptr = getservbyname("domain", "udp");  // DNS using UDPsptr = getservbyname("ftp", "tcp");//FTP using TCPsptr = getservbyname("ftp", NULL); //FTP using TCPsptr = getservbyname("ftp", "udp");// this call will fail
由于FTP仅支持TCP,所以第二个和第三个调用 是相同的,第四个调用将失败。

下一个函数getservbyport在给定端口号和可选协议后查找相应的服务

#include <netdb.h>struct servent *getservbyport(int port, const char *protoname);
成功返回非空指针,失败返回空指针

port为网络字节序。对此函数的典型调用是:

struct servent *sptr;sptr = getservbyport(htons(53), "udp"); // DNS using UDPsptr = getservbyport(htons(21), "tcp");//FTP using TCPsptr = getservbyport(htons(21), NULL);//FTP using TCPsptr = getservbyport(htons(21), "udp");// this call will fail


代码如下:

#include <netdb.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <sys/socket.h>#include <unistd.h>#include <netinet/in.h>#include <arpa/inet.h>#define MAXLINE 128char *sock_ntop(const struct sockaddr* sa, socklen_t salen){char portstr[7];static char str[MAXLINE];switch (sa->sa_family) {case AF_INET:{struct sockaddr_in *sin = (struct sockaddr_in*)sa;if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) return NULL;if (ntohs(sin->sin_port) != 0) {snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port));strcat(str, portstr);}return str;}}}int main(int argc, char **argv){int sockfd, n;char recvline[MAXLINE + 1];struct sockaddr_in servaddr;struct in_addr **pptr;struct hostent *hp;struct servent *sp;if (argc != 3) {printf("usage: execname <hostname> <service> \n");return -1;}if ((hp = gethostbyname(argv[1])) == NULL) {printf("hostname error for %s:%s\n", argv[1],  hstrerror(h_errno));return -1;}if ((sp = getservbyname(argv[2], "tcp")) == NULL) {printf("getservbyname error for %s:%s\n", argv[2], hstrerror(h_errno));return -1;}pptr = (struct in_addr**)hp->h_addr_list;for (; *pptr != NULL; pptr++) {sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {printf("socket error:%s\n", strerror(errno));return -1;}bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = sp->s_port;memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));printf("addr=%s, port=%d\n", inet_ntoa(**pptr), ntohs(sp->s_port));printf("trying %s\n", sock_ntop((struct sockaddr*)&servaddr, sizeof(servaddr)));if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == 0) break;printf("connect error:%s\n", strerror(errno));close(sockfd);}if (*pptr == NULL) {printf("unable to connect\n");return -1;}while ((n = read(sockfd, recvline, MAXLINE)) > 0) {recvline[n] = 0;fputs(recvline, stdout);}return 0;}

输出为:

0 0
原创粉丝点击