1、简介(1)

要编写通过计算机网络通信的程序,首先要确定这些程序相互通信所用的协议。(如何编写出独立于协议的应用程序??,比如:独立于IPV4和IPV6,移植方便)

http://m.blog.csdn.net/article/details?id=44280335(按照readme里面注释完成之后,有一点需要修改,如下)

1、一个简单的时间获取客户程序

下面是修改后的运行情况:

说明:

行13~14:socket函数创建一个网际(AF_INET)字节流(SOCK_STREAM)套接字,它是TCP套接字的别名。该函数返回一个小整数描述符,以后的所有函数调用(如后面的connect和read)就用该描述符来标识这个套接字。第14行是在套接字调用失败后,执行自己的err_sys函数放弃程序运行。

行16~20:先使用bzero函数使结构体sockaddr_in的变量servaddr清零;使用servaddr.sin_family=AF_INET;使地址族为AF_INET。端口号servaddr.sin_port = htons(13),端口号为13(13是时间获取服务器的众所周知端口号).这是服务器的操作。因为网际套接字地址结构中IP地址和端口号这两个成员必须使用特定格式,因此调用库函数htons(主机字节序到网络字节序短整数)去转换二进制端口号,又调用库函数inet_pton(呈现形式到数值)去把ASCII命令参数(例如本例中的127.0.0.1)转换为合适的格式。

注意:此处的inet_pton函数,它是一个支持IPV6的新函数。以前的代码使用inet_addr函数来把ASCII点分十进制数串变换成正确的格式,不过它有不少局限,而这些局限在inet_pton中得以纠正。

行22~23:建立与服务器的连接。connect函数应用与一个TCP套接字时,将与 由它的第二个参数指向的套接字地址结构指定的服务器建立一个TCP连接。这里在头文件unp.h中,把struct sockaddr 定义为SA,也就是通用套接字地址结构。每当一个套接字函数需要一个指向某个套接字地址结构的指针时,这个指针必须强制类型转换成一个指向通用套接字地址结构的指针

行25~28:首先使用read函数读取服务器的应答,并用标准的I/O函数fputs输出结果。使用TCP时必须小心,因为TCP是一个没有记录边界的字节流协议。其通常应答是格式为26字节字符串,如下:

Mon May 26 20:28:40 2003

其中 是ASCII回车符, 是ASCII换行符。一般从TCP读取数据时,总是需要把read编写在某个循环中,当read返回0(表示对端关闭连接)或负值(表明发生错误)时终止循环。

行33:终止程序。exit终止程序运行。unix在一个进程终止时总是关闭该进程所打开的描述符,我们的TCP套接字就此被关闭。

补充知识:计算机网络各层对等实体间交换的单位信息称为协议数据单元(protocol data unit,PDU),分节(segment)就是对应于TCP传输的PDU。

按照协议与服务之间的关系,除了最底层(物理层)外,每层的PDU通过由紧邻下层提供给本层的服务接口,作为下层的服务数据单元(service data unit,SDU)传递给下层,并由下层间接完成本层的PDU交换。如果本层的PDU大小超过紧邻下层的最大SDU限制,那么本层还要事先把PDU划分成若干个合适的片段让下层分开载送,再在相反方向把这些片段重组成PDU。同一层内SDU作为PDU的净荷字段出现,因此可以说上层PDU由本层PDU(通过其SDU字段)承载。每层的PDU除了用于承载紧邻上层的PDU外,也用于承载本层协议内部通信所需的控制信息。

应用层实体(如客户或服务器进程)间交换的PDU称为应用数据,其中在TCP应用进程之间交换的是没有长度限制的单个双向字节流,在UDP应用进程之间交换的是其长度不超过UDP发送缓冲区大小的单个记录(record),在SCTP应用进程之间交换的是没有总长度限制的单个或多个双向记录流。

传输层实体(如对应某个端口的传输层协议代码的一次运行)间交换的PDU称为消息(message),其中TCP的PDU称为分节(segment)。消息或分节的长度是有限的。在TCP传输层中,发送端TCP把来自应用程序的字节流数据(即应用进程通过一次次输出操作写出到发送端TCP套接字中的数据)按顺序经分割后封装在各个分节中传送给接收端TCP,其中每个分节所封装的数据即可能是发送端应用进程单次输出操作的结果,也可能是连续数次输出操作的结果,而且每个分节所封装的单次输出操作额结果或者首尾两次输出操作的结果即可能是完整的,也可能是不完整的,具体取决于可在连接建立阶段由对端通告的最大分节大小(maximum segment size,MSS)以及外出接口的最大传输单元(maximum transmission unit,MTU)或外出路径的路径MTU。分节除了用于承载应用数据外,也用于建立连接(SYN分节)、终止连接(FIN分节)、中止连接(RST 分节)、确认数据接收(ACK分节)、刷送待发数据(PSH分节)和携带紧急数据指针(URG分节),而且这些功能(包括承载数据)可以灵活组合。

UDP传输层相当简单,发送端UDP就把来自应用层进程的单个记录整个封装在UDP消息中传送给接收端UDP。

SCTP引入了称为块(chunk)的数据单元,SCTP消息就由一个公共首部加上一个或多个块构成:公共首部类似UDP消息的首部,仅仅给出源目的端口号和整个SCTP消息的校验和;块则即可以承载数据(称为DATA块),也可以承载控制信息。发送端SCTP把来自应用进程的(一个或多个)记录流数据按照流内顺序和记录边界封装在各个DATA块中,并在DATA块首部记上各自的流ID。一个记录通常对应一个DATA块;对于过长的记录,发送端SCTP即可以像UDP那样拒绝发送,也可以把他们拆分到多个DATA块中以便发送,接收端SCTP收取后把他们组合成单个记录上传。作为传输层PDU的SCTP消息即可以包含单个块,也可以在接口MTU或路径MTU的限制下包含多个块(称为块的捆绑,控制块在前,数据块在后)。

网络层实体间交换的PDU称为IP数据报,其长度有限,IPV4数据报最大65535字节,IPV6数据报最大65575字节。发送端IP把来自传输层的消息(或TCP分节)整个封装在IP数据报中传送。IP数据报由IP首部和所承载的传输层数据(即网络层的SDU)构成。过长的IP数据报无法封装在单个帧中,需要先对其SDU进行分片,再把分成的各个片段冠以新的IP首部封装到多个帧中。在一个IP数据报从源端到目的端的传送过程中,分片操作既可能发生在源端,也可能发生在途中,而其逆朝族即重组(reassembly)一般只发生在目的端。

链路层实体间交换的PDU称为帧(frame),其长度取决于具体的接口。

原文地址:https://www.cnblogs.com/gary-guo/p/5976496.html