📄 00000006.htm
字号:
int gethostname(char *hostname, size_t size); <BR>参数很简单:hostname 是一个字符数组指针,他将在函数返回时保存主机名。size 是 <BR> hostname 数组的字节长度。 <BR>函数调用成功时返回 0,失败时返回 -1,并设置 errno。 <BR>DNS--You say "whitehouse.gov", I say "198.137.240.100" <BR>如果你不知道 DNS 的意思,那么我告诉你,他代表"域名服务 (Domain Name <BR>Service)"。他主要的功能是:你给他一个容易记忆的某站点的地址,他给你 IP 地址( <BR>然后你就可以使用 bind(), connect(), <BR>sendto() 或者其他函数。)当一个人输入: <BR> $ telnet whitehouse.gov <BR>telnet 能知道他将连接 (connect()) 到 "198.137.240.100"。 <BR>但是这是如何工作的呢? 你可以调用函数 gethostbyname(): <BR> #include <netdb.h> <BR> struct hostent *gethostbyname(const char *name); <BR>很明白的是,他返回一个指向 struct hostent 的指针。这个数据结构是这样的: <BR> struct hostent { <BR> char *h_name; <BR> char **h_aliases; <BR> int h_addrtype; <BR> int h_length; <BR> char **h_addr_list; <BR> }; <BR> #define h_addr h_addr_list[0] <BR>这里是这个数据结构的详细资料: struct hostent: <BR> h_name - Official name of the host. <BR> h_aliases - A NULL-terminated array of alternate names for the host. <BR> h_addrtype - The type of address being returned; usually AF_INET. <BR> h_length - The length of the address in bytes. <BR> h_addr_list - A zero-terminated array of network addresses for the host. <BR> <BR> Host addresses are in Network Byte Order. <BR> h_addr - The first address in h_addr_list. <BR>gethostbyname() 成功时返回一个指向 struct hostent 的指针,或者是个空 (NULL) <BR>指针。(但是和以前不同,errno <BR>不设置,h_errno 设置错误信息。请看下面的 herror()。) <BR>但是如何使用呢? 这个函数可不象他看上去那么难用。 <BR>这里是个例子: <BR> #include <stdio.h> <BR> #include <stdlib.h> <BR> #include <errno.h> <BR> #include <netdb.h> <BR> #include <sys/types.h> <BR> #include <netinet/in.h> <BR> int main(int argc, char *argv[]) <BR> { <BR> struct hostent *h; <BR> if (argc != 2) { /* error check the command line */ <BR> fprintf(stderr,"usage: getip address\n"); <BR> exit(1); <BR> } <BR> if ((h=gethostbyname(argv[1])) == NULL) { /* get the host info */ <BR> herror("gethostbyname"); <BR> exit(1); <BR> } <BR> printf("Host name : %s\n", h->h_name); <BR> printf("IP Address : %s\n",inet_ntoa(*((struct in_addr *)h->h_addr)) <BR>); <BR> return 0; <BR> } <BR>在使用 gethostbyname() 的时候,你不能用 perror() 打印错误信息(因为 errno 没有 <BR>使用),你应该调用 herror()。 <BR>相当简单,你只是传递一个保存机器名的自负串(例如 "whitehouse.gov") 给 gethost <BR>byname(),然后从返回的数据结构 struct <BR>hostent 中收集信息。 <BR>唯一让人迷惑的是打印 IP 地址信息。h->h_addr 是一个 char *,但是 inet_ntoa() <BR>需要的是 struct <BR>in_addr。因此,我转换 h->h_addr 成 struct in_addr *,然后得到数据。 <BR>Client-Server Background <BR>这里是个客户--服务器的世界。在网络上的所有东西都是在处理客户进程和服务器进程 <BR>的交谈。举个 telnet 的例子。当你用 telnet (客户)通过 23 <BR>号端口登陆到主机,主机上运行的一个程序(一般叫 telnetd,服务器)激活。他处理这 <BR>个连接,显示登陆界面,等等。 <BR>Figure 2. The Client-Server Relationship. <BR>图 2 说明了客户和服务器之间的信息交换。 <BR>注意,客户--服务器之间可以使用SOCK_STREAM、SOCK_DGRAM 或者其他(只要他们采用相 <BR>同的)。一些很好的客户--服务器的例子有 <BR>telnet/telnetd、 ftp/ftpd 和 bootp/bootpd。每次你使用 ftp 的时候,在远端都有 <BR>一个 ftpd 为你服务。 <BR>一般,在服务端只有一个服务器,他采用 fork() 来处理多个客户的连接。基本的程序 <BR>是:服务器等待一个连接,接受 (accept()) 连接,然后 fork() <BR>一个子进程处理他。这是下一章我们的例子中会讲到的。 <BR>简单的服务器 <BR>这个服务器所做的全部工作是在留式连接上发送字符串 "Hello, World!\n"。你要测试 <BR>这个程序的话,可以在一台机器上运行该程序,然后在另外一机器上登陆: <BR> $ telnet remotehostname 3490 <BR>remotehostname 是该程序运行的机器的名字。 <BR>服务器代码: <BR> #include <stdio.h> <BR> #include <stdlib.h> <BR> #include <errno.h> <BR> #include <string.h> <BR> #include <sys/types.h> <BR> #include <netinet/in.h> <BR> #include <sys/socket.h> <BR> #include <sys/wait.h> <BR> #define MYPORT 3490 /* the port users will be connecting to */ <BR> #define BACKLOG 10 /* how many pending connections queue will hold * <BR>/ <BR> main() <BR> { <BR> int sockfd, new_fd; /* listen on sock_fd, new connection on new_fd <BR>*/ <BR> struct sockaddr_in my_addr; /* my address information */ <BR> struct sockaddr_in their_addr; /* connector's address information */ <BR> <BR> int sin_size; <BR> if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { <BR> perror("socket"); <BR> exit(1); <BR> } <BR> my_addr.sin_family = AF_INET; /* host byte order */ <BR> my_addr.sin_port = htons(MYPORT); /* short, network byte order * <BR>/ <BR> my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */ <BR> bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct <BR> */ <BR> if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr <BR>)) \ <BR> == -1) <BR> { <BR> perror("bind"); <BR> exit(1); <BR> } <BR> if (listen(sockfd, BACKLOG) == -1) { <BR> perror("listen"); <BR> exit(1); <BR> } <BR> while(1) { /* main accept() loop */ <BR> sin_size = sizeof(struct sockaddr_in); <BR> if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, \ <BR> &sin_size)) == -1) <BR> { <BR> perror("accept"); <BR> continue; <BR> } <BR> printf("server: got connection from %s\n", \ <BR> inet_ntoa(their_addr.sin_addr <BR>)); <BR> if (!fork()) { /* this is the child process */ <BR> if (send(new_fd, "Hello, world!\n", 14, 0) == -1) <BR>&nbs
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -