socket(2)

1949阅读 0评论2012-08-22 zhongli_i
分类:LINUX

    之前一篇文章中socket的客户和服务器程序都把端口号和地址编译到内部,对于通用的服务器和客户程序来说,可以通过网络信息函数来决定应该使用的地址和端口。
    对于客户端,如果给定一个计算机的名字,可以通过调用解析地址的主机数据库函数来确定他的IP地址,主机数据库函数通过查询网络配置文件来完成。
    主机数据库函数包括

点击(此处)折叠或打开

  1. struct hostent *gethostbyaddr(const void *addr,size_t len,int tyype);
  2. struct hostent *gethostbyname(const char *name);
  3. //函数返回值包括
  4. struct hostent
  5. {
  6.   char *h_name; //主机名
  7.   char **h_aliases
  8.   int h_addrtype; //地址类型
  9.   int h_length; //地址字节数
  10.   char **h_addr_list
  11. };
未找到相关主机或地址相关数据项,返回空指针。
 
服务器端与关联端口号有关的信息通过服务信息函数获取,如下:

点击(此处)折叠或打开

  1. struct servent *getservbyname(const char *name,const char *proto);
  2. struct servent *getservbyport(int port,const char *proto);
proto为用于连接该服务的协议,TCP/UDP,返回值包括设备名,IP端口号,协议类型等。
下面例程为一个客户程序,使他连接到任何有名字的主机。连接到一个标准服务器,查看端口号的提取操作。这里用的服务是daytime服务,大多数unix和linux系统都有这一标准服务,客户可以连接到这个服务来查看服务器当前的日期和时间。
/*  头文件及变量声明  */

点击(此处)折叠或打开

  1. #include <sys/socket.h>
  2. #include <netinet/in.h>
  3. #include <netdb.h>
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <stdlib.h>

  7. int main(int argc, char *argv[])
  8. {
  9.     char *host;
  10.     int sockfd;
  11.     int len, result;
  12.     struct sockaddr_in address;//套接字地址
  13.     struct hostent *hostinfo; //主机信息,主机名或IP地址等
  14.     struct servent *servinfo; //服务器信息,关联的端口号等
  15.     char buffer[128];

  16.     if(argc == 1) //把用户主机的主机名设置为localhost
  17.         host = "localhost";
  18.     else
  19.         host = argv[1];//主机名设置为命令行参数
/*  找主机地址,若找不到则报告错误  */

点击(此处)折叠或打开

  1. hostinfo = gethostbyname(host); //从主机数据库中提取主机信息 主机名为host 即localhost
  2.     if(!hostinfo)
  3.  {
  4.         fprintf(stderr, "no host: %s\n", host);
  5.         exit(1);
  6.     }
/*  查看主机上是否有daytime服务  */

点击(此处)折叠或打开

  1. servinfo = getservbyname("daytime", "tcp");//获取daytime服务,其类型为TCP 相关信息
  2.     if(!servinfo) //通过getservbyname来获得该服务的端口号
  3. {
  4.         fprintf(stderr,"no daytime service\n");
  5.         exit(1);
  6.     }
  7.     printf("daytime port is %d\n", ntohs(servinfo -> s_port));//存在则打印所在的IP端口号
/*  创建一个新的未命名套接字  */

点击(此处)折叠或打开

  1. sockfd = socket(AF_INET, SOCK_STREAM, 0);
/*  命名套接字,构造connect调用要使用到的地址  */

点击(此处)折叠或打开

  1. address.sin_family = AF_INET;
  2. address.sin_port = servinfo -> s_port;//客户端口为daytime服务的IP端口
  3. address.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list;
  4. len = sizeof(address);
/*  建立连接获取相关信息  */

点击(此处)折叠或打开

  1. result = connect(sockfd, (struct sockaddr *)&address, len);//向该主机该服务发出连接请求
  2.     if(result == -1) {
  3.         perror("oops: getdate");
  4.         exit(1);
  5.     }
  6. //已获取连接,则将socket内容读到buffer
  7.     result = read(sockfd, buffer, sizeof(buffer));
  8.     buffer[result] = '\0';
  9.     printf("read %d bytes: %s", result, buffer);

  10.     close(sockfd);//关闭socket
  11.     exit(0);
  12. }
运行./getdate 显示
daytime port is 13
read 26 bytes: 22 AUG 2012 12:32:48 CST
这个程序可以指定要连接的主机,daytime服务的端口号通过getservbyname获得,函数返回网络服务相关的信息,socket连接到指定主机返回的地址列表中第一个地址,连接成功就读取daytime服务返回的信息,一个表示linux日期和时间的字符串。
上一篇:网络编程接口socket
下一篇:socket(3)