之前一篇文章中socket的客户和服务器程序都把端口号和地址编译到内部,对于通用的服务器和客户程序来说,可以通过网络信息函数来决定应该使用的地址和端口。
对于客户端,如果给定一个计算机的名字,可以通过调用解析地址的主机数据库函数来确定他的IP地址,主机数据库函数通过查询网络配置文件来完成。
主机数据库函数包括
- struct hostent *gethostbyaddr(const void *addr,size_t len,int tyype);
- struct hostent *gethostbyname(const char *name);
- //函数返回值包括
- struct hostent
- {
- char *h_name; //主机名
- char **h_aliases
- int h_addrtype; //地址类型
- int h_length; //地址字节数
- char **h_addr_list
- };
未找到相关主机或地址相关数据项,返回空指针。
服务器端与关联端口号有关的信息通过服务信息函数获取,如下:
- struct servent *getservbyname(const char *name,const char *proto);
- struct servent *getservbyport(int port,const char *proto);
proto为用于连接该服务的协议,TCP/UDP,返回值包括设备名,IP端口号,协议类型等。
下面例程为一个客户程序,使他连接到任何有名字的主机。连接到一个标准服务器,查看端口号的提取操作。这里用的服务是daytime服务,大多数unix和linux系统都有这一标准服务,客户可以连接到这个服务来查看服务器当前的日期和时间。
/* 头文件及变量声明 */
- #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; //主机信息,主机名或IP地址等
- struct servent *servinfo; //服务器信息,关联的端口号等
- char buffer[128];
- if(argc == 1) //把用户主机的主机名设置为localhost
- host = "localhost";
- else
- host = argv[1];//主机名设置为命令行参数
/* 找主机地址,若找不到则报告错误 */
- hostinfo = gethostbyname(host); //从主机数据库中提取主机信息 主机名为host 即localhost
- if(!hostinfo)
- {
- fprintf(stderr, "no host: %s\n", host);
- exit(1);
- }
/* 查看主机上是否有daytime服务 */
- servinfo = getservbyname("daytime", "tcp");//获取daytime服务,其类型为TCP 相关信息
- if(!servinfo) //通过getservbyname来获得该服务的端口号
- {
- fprintf(stderr,"no daytime service\n");
- exit(1);
- }
- printf("daytime port is %d\n", ntohs(servinfo -> s_port));//存在则打印所在的IP端口号
/* 创建一个新的未命名套接字 */
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* 命名套接字,构造connect调用要使用到的地址 */
- address.sin_family = AF_INET;
- address.sin_port = servinfo -> s_port;//客户端口为daytime服务的IP端口
- address.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list;
- len = sizeof(address);
/* 建立连接获取相关信息 */
- result = connect(sockfd, (struct sockaddr *)&address, len);//向该主机该服务发出连接请求
- if(result == -1) {
- perror("oops: getdate");
- exit(1);
- }
- //已获取连接,则将socket内容读到buffer
- result = read(sockfd, buffer, sizeof(buffer));
- buffer[result] = '\0';
- printf("read %d bytes: %s", result, buffer);
- close(sockfd);//关闭socket
- exit(0);
- }
运行./getdate 显示
daytime port is 13
read 26 bytes: 22 AUG 2012 12:32:48 CST
这个程序可以指定要连接的主机,daytime服务的端口号通过getservbyname获得,函数返回网络服务相关的信息,socket连接到指定主机返回的地址列表中第一个地址,连接成功就读取daytime服务返回的信息,一个表示linux日期和时间的字符串。
阅读(1971) | 评论(0) | 转发(1) |