通过一个C应用程序分析BSD应用的特点
/* Send a UDP datagram to the daytime server on some host, read the reply,and print the time and date on the server. */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define BUFFSIZE 150 /*arbitrary size*/ int main() { struct sockaddr_in serv; char buff[BUFFSIZE]; int sockfd,n; if((sockfd = socket(PF_INET,SOCK_DGRAM,0))<0) err_sys("socket error"); bzero((char*)&serv,sizeof(serv)); serv.sin_family=AF_INET; serv.sin_addr.s_addr=inet_addr("140.252.1.32"); serv.sin_port=htons(13); if(sendto(sockfd,buff,BUFFSIZE,0,(struct sockaddr *)&serv,sizeof(serv))!=BUFFSIZE) err_sys("sendto error"); if((n=recvfrom(sockfd,buff,BUFFSIZE,0,(struct socketaddr *)NULL,(int *)NULL))<2) err_sys("recvfrom error"); buff[n-2]=0; /*null terminate*/ printf("%s\n",buff); exit(0); }//程序实例:发送一个数据报给UDP日期/时间服务器并读取一个应答。
1.创建一个数据报socket
21-22:socket函数创建了一个UDP socket,并且给进程返回一个保存在变量sockfd中的描述符,err_sys是差错处理函数。它接受任意数量的参数,并用vsprintf对它们格式化,将系统调用产生的errno值对应的Unix错误信息打印出来,并中断进程。
我们在不同的地方使用术语socket:
1)为4.2BSD开发的程序用来访问网络协议的API通常叫socket API或者socket接口。
2)socket是socket API中的一个函数的名字。
3)我们把调用Socket创建的端点叫做一个socket,如评注“创建一个数据报socket”。
但这里还有一些地方也使用术语socket:
4)socket函数的返回值叫一个socket描述符或者就叫一个socket。
5)在内核中的伯克利联网协议叫socket实现,相比较其他系统如:系统V的流实现。
6)一个IP地址和一个端口号的组合叫一个socket,IP地址和端口号对叫一个socket。
2.将服务器地址放到结构socketaddr_in中
23-26:在一个互联网socket地址结构中存放日期/时间服务器的IP地址(140.252.1.32)和端口号(13)。大多数TCP\IP实现多提供标准的日期/时间服务器,它的端口号是13。我们对服务器主机的选择是随意的---直接选择了提供此服务的本地主机。
函数inet_add将一个点分十进制表示的IP地址的ASCII字符串转换成网络字节序的32bit二进制整数。(Internet协议族的网络字节序是高字节在后)。函数htons把主机字节序的短整数(可能是低字节在后)转换成网络字节序(高字节在后)。在Sparc这种系统中,整数是高字节在后的格式,htons典型的是一个什么也不做的宏。但是在低字节在后的80386上的BSD/386系统中,htons可能是一个宏或者是一个函数,来完成一个16bit整数中的两个字节的交换。
3.发送数据报给服务器
28-29:程序调用sendto发送一个150字节的数据报给服务器。因为是运行时栈中分配的未初始化数组,150字节的缓存内容是不确定的。但没有关系,因为服务器根本就不看它收到的报文的内容。当服务器收到一个报文时,就发送一个应答给客户端。应答中包含服务器以可读格式表示的时间和日期。
我们选择的150字节的客户数据报是随意的。我们有意选择一个报文长度在100-208之间的值,来说明后面要提到的mbuf链表的使用。为了避免阻塞,在以太网中,我们希望长度要小于1472。
4.读取从服务器返回的数据报
30-33:程序通过调用recvfrom来读取从服务器发回的数据报。Unix服务器典型地返回一个如下格式的26字节字符串
Sat Dec 11 11:28:05 1993\r\n
\r是一个ASCII回车符,\n是ASCII换行符。我们的程序将回车符替换成一个空字节,然后调用printf输出结果。