chentc

通过一个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输出结果。


posted on 2011-05-19 08:51  chentc  阅读(328)  评论(0编辑  收藏  举报

导航