第13章 TCP/IP和网络编程
摘要
本章论述了TCP/IP 和网络编程,分为两个部分。第一部分论述了TCP/IP协议及其应用,具体包括 TCP/IP 栈、IP地址、主机名、DNS、IP数据包和路由器;介绍了TCP/IP 网络中的UDP和 TCP 协议、端口号和数据流;阐述了服务器-客户机计算模型和套接字编程接口;通过使用UDP和TCP套接字的示例演示了网络编程。第一个编程项目可实现一对通过互联网执行文件操作的 TCP服务器-客户机,可让用户定义其他通信协议来可靠地传输文件内容。
本章的第二部分介绍了Web和CGI编程,解释了HTTP编程模型、Web 页面和 Web浏览器;展示了如何配置 Linux HTTPD服务器来支持用户 Web 页面、PHP和CGI编程;阐释了客户机和服务器端动态 Web 页面;演示了如何使用PHP和 CGI创建服务器端动态Web 页面。
13.2 TCP/IP协议
TCP/IP(Comer 1988,2001;RFC1180 1991)是互联网的基础。TCP代表传输控制协议。IP 代表互联网协议。目前有两个版本的IP,即IPv4和IPv6。IPv4使用32位地址,IPv6则使用128位地址。本节围绕IPv4 进行讨论,它仍然是目前使用最多的IP版本。TCP/IP 的组织结构分为几个层级,通常称为TCP/IP堆栈。如图所示为 TCP/IP 的各个层级以及每一层级的代表性组件及其功能。
顶层是使用TCP/IP的应用程序。用于登录到远程主机的ssh、用于交换电子邮件的mail、用于Web页面的合同谈判等应用程序需要可靠的数据传输。通常,这类应用程序在传输层使用TCP。另一方面,有些应用程序,例如用于查询其他主机的ping命令,则不需要可靠性。这类应用程序可以在传输层使用UDP来提高效率。传输层负责以包的形式向IP主机发送/接收来自IP主机的应用程序数据。进程与主机之间的传输层或其上方的数据传输只是逻辑传输。实际数据传输发生在互联网(IP)和链路层,这些层将数据包分成数据帧,以便在物理网络之间传输。
13.3 IP主机和IP地址
IP地址分为两部分,即 NetworkID 字段和HostID字段。根据划分,IP 地址分为A~E 类。例如,一个B类IP地址被划分为一个16位NetworkID,其中前2位是10,然后是一个16位的 HostID字段。发往IP地址的数据包首先被发送到具有相同 networkID的路由器。路由器将通过 HostID 将数据包转发到网络中的特定主机。每个主机都有一个本地主机名localhost,默认 IP地址为 127.0.0.1。本地主机的链路层是一个回送虚拟设备,它将每个数据包路由回同一个localhost。这个特性可以让我们在同一台计算机上运行TCP/IP 应用程序,而不需要实际连接到互联网。
13.4 IP协议
IP协议用于在IP主机之间发送/接收数据包。IP尽最大努力运行。IP主机只向接收主机发送数据包,但它不能保证数据包会被发送到它们的目的地,也不能保证按顺序发送。这意味着IP并非可靠的协议。必要时,必须在IP层上面实现可靠性。
13.5 IP数据包格式
IP数据包由IP头、发送方IP地址和接收方IP地址以及数据组成。每个IP数据包的大小最大为64KB.IP头包含有关数据包的更多信息,例如数据包的总长度、数据包使用TCP还是UDP、生存时间(TTL)计数、错误检测的校验和等。
13.7 UDP/TCP
UDP(用户数据报协议)在IP上运行,用于发送/接收数据报。与IP相似,UDP不能保证可靠性,但是快速高效。用户可以使用ping命令探测目标主机,如ping主机名或pingIP地址
TCP(传输控制协议)是一种面向连接的协议,用于发送/接收数据流。TCP也可在IP上运行,但它保证了可靠的数据传输。
UDP类似于发送邮件的USPS,而TCP类似于电话连接。
13.9 端口编号
应用程序=(主机IP,协议,端口号)
其中,协议是TCP或 UDP,端口号是分配给应用程序的唯一无符号短整数。要想使用UDP或 TCP,应用程序(进程)必须先选择或获取一个端口号。前1024个端口号已被预留。其他端口号可供一般使用。应用程序可以选择一个可用端口号,也可以让操作系统内核分配端口号。下图给出了在传输层中使用TCP 的一些应用程序及其默认端口号。
13.11 TCP/IP网络中的数据流
在图中,应用程序层的数据被传递到传输层,传输层给数据添加一个TCP或UDP 报头来标识使用的传输协议。合并后的数据被传递到IP 网络层,添加一个包含 IP地址的IP 报头来标识发送和接收主机。然后,合并后的数据再被传递到网络链路层,网络链路层将数据分成多个帧,并添加发送和接收网络的地址,用于在物理网络之间传输。IP地址到网络地址的映射由地址解析协议(ARP)执行(ARP1982)。在接收端,数据编码过程是相反的。每一层通过剥离数据头来解包接收到的数据、重新组装数据并将数据传递到上一层。发送主机上的应用程序原始数据最终会被传递到接收主机上的相应应用程序。
13.13 套接字编程
13.13.1 套接字地址
struct sockaddr_in {
sa_family_t sin_family; // AF_INET for TCP/IP
in_port_t sin_port; //port number
struct in_addr sin_addr; // IP address
};
struct in_addr { //internet address
uint32_t s_addr; //IP address in network byte order
};
在套接字地址结构中,
-
TCP/IP 网络的 sin_family 始终设置为 AF_INET。
-
sin_port包含按网络字节顺序排列的端口号。
-
sin addr是按网络字节顺序排列的主机IP地址。
13.13.2 套接字API
服务器必须创建一个套接字,并将其与包含服务器IP 地址和端口号的套接字地址绑定。它可以使用一个固定端口号,或者让操作系统内核选择一个端口号(如果 sin port为0)。为了与服务器通信,客户机必须创建一个套接字。对于UPD套接字,可以将套接字绑定到服务器地址。如果套接字没有绑定到任何特定的服务器,那么它必须在后续的 sendto()/recvfrom()调用中提供一个包含服务器IP 和端口号的套接字地址。
TCP/UDP套接字
UDP 套接字使用 sendto(/recvfrom(来发送/接收数据报。
ssize_t sendto(int soCkfd,const void *buf,size_t len,int flags,
const struct sockaddr *dest_addr,socklen_t addrlen);
ssize_t recvfrom(int sockfd,void *buf,size_t len,int flags,
struct sockaddr *src_addr,socklen_t *addrlen);
在创建套接字并将其绑定到服务器地址之后,TCP服务器使用listen()和 accept()来接收来自客户机的连接
int listen(int sockfd, int backlog);
listen()将 sockfd引用的套接字标记为将用于接收连人连接的套接字。backlog 参数定义了等待连接的最大队列长度。
int accept(int sockfd, struct sockaddr *addr, socklen t *addrlen);
标签:IP,编程,TCP,Unix,应用程序,Linux,接字,数据包,端口号
From: https://www.cnblogs.com/qwer6653/p/16884501.html