最后更新:2021-11-22 20:58:04 手机定位技术交流文章
本章第一部分涉及TCP/IP协议及其应用,涉及TCP/IP堆叠、IP地址、主机名、DNS、IP数据集和路由器;后半部分提供UDP和TCP协议、端口号以及TCP/IP网络的数据流;讨论服务器-客户计算模型和套件界面;通过使用UDP和TCP软件包的例子显示网络编程。
本章第二节涵盖网络和地理信息中心编程,包括对HTTP编程模式、网页和浏览器的解释,以及如何设置Linux HTTPD服务器处理用户网页、PHP和CGI编程,对客户和服务器终端动态网页的解释,以及展示如何利用HP和CGI建立服务器终端动态网页。

一. TCP/IP协议协议
TCP/IP (Comer 1988; 2001; RFC 1180 1991)是互联网的基础。 TCP 代表传输控制协议。 IP 代表互联网协议。 现在有两种形式的IP, IPv4 和 IPv6.IPv4 使用32个地址, IPv6 使用128个地址。 本节介绍IPv4, IPv4仍然是最广泛使用的IP版本。 TCP/IP 的结构分为几层, 通常称为 TCP/IP 堆叠。

程序与主机层之间或以上的数据传输只是合乎逻辑的。真正的数据传输发生在互联网(IP)和链层上,后者将数据包分割成数据框,供物理网络之间传输。下图描述了TCP/IP网络中的数据流路径。

二. IP 主机和IP地址
IP 地址分为两个部分, 网络ID 字段和 HostID 字段。 分解后, IP 地址被分类为 A- E 。 例如, B 类中的IP 地址被分为16位网络ID, 其中前两位为 10, 后一位是 16 位 HostID 字段。 发送到 IP 地址的软件包先被发送到与同一网络WorkingID 相同的路由器。 路由器将通过 HostID 将软件包转发给网络中的特定主机 。 每个主机都有一个本地主机名, 本地主机, 以及默认的 IP 地址 。 本地主机链层是一个返回虚拟设备, 将每个数据包返回同一本地主机 。 此功能允许我们在同一计算机上运行 TCP/ IP 应用程序, 而不实际连接互联网 。
3.IP协议
IP 协议用于在 IP 主机之间发送/接收数据包 。 IP 主机只需将软件包传送给接收者, 但它不能确保软件包将传送到其目的地或按顺序发送。 这意味着 IP 不是一个可靠的协议。 如果需要可靠性, 则必须在 IP 层上方建立可靠性 。

4.UDP/TCP
UDP(用户数据报告协议)(RFC768,1980年;Comer 1988年)是一个关于IP的协议,用于传输和接收数据报告。 和IP一样,UDP并不保证可靠性,而是快速有效的,可以在可靠性并不关键的情况下使用。
TCP(传输控制协议)是用于传输/接收数据流的以连接为导向的协议。 TCP也可能在 IP 上运行,但它提供一致的数据传输。 UDP通常用于发送邮件,但TCP被用于发送数据流。
5.端口编号
应用程序 = (主机IP地址、协议和端口)
协议是 TCP 或 UDP, 端口号是分配给程序的唯一未签名的短整数 。 要使用 UDP 或 TCP, 应用程序( process) 必须首先选择或获得端口号 。 保留了第一个 1024 端口号 。 其他端口号可供一般使用 。 应用程序可以选择可用的端口号, 也可以在操作系统中进行核分配 。

第六,TCP/IP网络中的数据流

在图表中,应用层的数据传递到传输层,该层在数据中添加一个 TCP 或 UDP 信头以标记所使用的传输协议。合并的数据传递到 IP 网络层,添加IP 信头以标记发送和接收主机。合并的数据随后传输到网络链层,将数据分为多个框架,并添加发送和接收网络在物理网络之间传输的地址。IP 地址到网络地址的地图由地址解析协议(ARP 1982年)执行。在接收端,数据编码程序是相反的。Each 层通过删除数据头、重新组装数据并将数据传输到前一级的方式删除收到的数据。Send the 应用程序的原始数据将最终传递给接收者的相应应用程序。
7.套接字编程
(1)套接字地址
struct sockaddr_in {
sa_family_t sin_family; // AF_INET for TCP/IP
// port number
in_port_t sin_port;
struct in_addr sin_addr;// IP address );
// internet address struct in_addr {
// IP address in network byte order
s_addr;
uint32_t
);
在Socket地址结构框架内,
· TCP/IP网络的Sin_Family总是设于AF_INET。
• Sin_port仓库港口号,按网络字节的顺序排列。
* Sin addr 是按网络字节顺序排列的主机 IP 地址。
(2)套接字API
服务器必须构造套接字, 并将其绑在带有服务器 IP 地址和端口号的套接字地址上。 它可以使用预设端口号码, 或者使操作系统能够选择端口号码( 如果罪过端口为零 ) 。 为了连接服务器, 客户端必须创建一个套接字 。 对于 UPD 设置, 您可以将其附加到服务器 地址构建器上。 对于 UPD 设置, 您可以将套接字附加到服务器 地址和端口号的套接字地址上。 它可以使用预设端口号码, 或者使操作系统能够选择端口号( 如果罪过端口为零 ) 。 为了连接服务器, 客户端口必须创建套接字。 For UPD 设置, 您可以将其附加到服务器地址 。
(3) TCP/UDP捆包
为了发送/接收数据报告,UDP Socket使用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 服务器使用听( ) 并接受( ) 接收客户的连接 。
int listen(int sockfd, int backlog);
后遗迹参数决定等待连接的最大队列长度 。 听 () 将 sockfd 所引用的合成标记为将用来接收连接的合成 。
int accept(int sockfd, struct sockaddr *addr, socklen t *addrlen);
(4) 通用套件地址结构
sockaddr 是一个常见的 Socket 地址结构 。
struct sockaddr
{
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};
IPv6套接字地址结构
IPv6套接字地址结构在<netinet/in.h>头文件中定义
struct in6_addr
{
unit8_t s6_add[16];
};
#define SIN6_LEN
struct sockaddr_in6
{
uint8_t sin6_len;
sa_family_t sin6_family;
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};
新的struct sockaddr_storage足以容纳系统所支持的任何套接字地址结构。sockaddr_storage结构在<netinet/in.h>头文件中定义
struct sockaddr_storage
{
uint8_t ss_len;
sa_family_t ss_family;
};
8.字节排序函数
末端,小端和大端(内存中两个字字节)
运算器(小半年):在起始地址中保留低顺序字节。
大(大) : 将高阶字节保留在起始地址 。
主机字节顺序:某一系统中使用的字节顺序。
输出字节序的程序:
#iclude"unp.h"
int main(int argc,char **argv)
{
union{
short s;
char c[sizeof(short)];
}un;
un.s=0x0102;
printf("%s:",CUP_VENDOR_OS);
if(sizeof(short)==2){
if(un.c[0]==1&&un.c[1]==2)
printf("big-endiann");
else if (un.c[0]==2&&un.c[1]==1)
printf("little-endiann");
else
printf("unknownn");
}else
printf("sizeof(short)=%dn",sizeof(short));
exit(0);
}
9.字节操纵函数
bzero: bzero 重置目标字节显示的字节数为零。 此函数经常用于将包件地址结构重置为零 。
bocpy: 将给定数目的字节从源移到目标字节字符串 。
bcmp:比较两个随机字节字符串,如果返回值相同,则返回 0;否则,返回值为非-0。
矩形 : 作为 c, 输入目标字节字符串中显示的字节数 。
菜单: 比较两个随机字符串, 返回一个大于或小于0的非零值, 取决于第一个变量字节 。
IPv4 兼容 nint_pton 函数的基本定义 :
int inet_pton(int family,const char *strptr,void *addrptr)
{
if(family==AF_INET)
{
struct in_addr in_val;
if(inet_aton(strptr,&in_val))
{
memcpy(addrptr,&in_val,sizeof(struct int_addr));
return(1);
}
return(0);
}
errno=EAFNOSUPPROT;
return(-1);
}
Web和CGI编程
万维网或万维网是互联网上使用超文本传输协议(RFC 2616 199)进行信息交流的资源和用户的结合。 自1990年代初期以来,随着因特网能力的不断增强,万维网已成为全世界人民日常生活中不可或缺的一部分。 因此,了解这一技术对学生的计算机科学非常重要。 在本节中,我们将介绍HTTP和网络程序的基本知识。Web编程通常包括参与网络开发的文字、标记和编码,包括网络内容、网络客户和服务器脚本以及网络安全。 在狭义上,网络编程是指创建和维持网页。 网络编程中最常用的语言是HTML、XHTML、JavaScript、 Perl5和PHP。
Http编程模型
HTTP是互联网应用程序的服务器客户协议,在TCP上运行,因为它需要可靠的文件传输。 图13描述了HTTP的编程模式。

在 HTTP 中, 客户可以发送多个 URL, 并向不同的 HTTP 服务器发送请求。 客户维持与特定服务器的永久连接既不必要也不可取。 客户仅为发送请求而与服务器连接, 在发送时将关闭连接。 类似地, 服务器仅为发送回复而连接到客户机, 发送后, 连接将再次关闭。 每一个请求或回复都要求单独连接。 这意味着 HTTP 是一个无效的协议, 因为不需要在连续的请求或回复之间保持任何信息。 NAturally, 这将导致巨大的系统成本和效率。 为了弥补这种缺乏状态信息的情况, HTTP 服务器和客户可以使用 cookie 来提供和维护它们之间的某些状态信息 。
Web界面
网页是 HTML 标记语言的文件。 网页文件通过可在 Web 浏览器上解释和显示的 HTML 组件序列来描述网页的结构。 comon 网络浏览器包括 Internet Explorer、 Firefox、 Google Chrome 等。 创建网页等于用 HTML 元素作为建筑块来制作文本文件。 它比编程要多, 不仅仅是文书工作 。
CGI编程
互联网服务器不必保留数百万个静态网页文件来回应客户的要求,而是通过动态制作网页来回应客户的要求。

客户端提交请求, 通常为 HTML 格式, 包括服务器运行的 CGI 程序输入和名称 。 收到请求后, httpd 服务器将有一个子程序执行 CGI 程序 。 CCGI 可以查询数据库系统, 如 MySQL, 使用用户输入来生成 HTML 文件, 取决于用户输入 。 当子进程完成后, httpd 服务器将由此产生的 HTML 文件发回客户端 。
代码链接:
https://gitee.com/two_thousand_and_thirteen/zx-code/issues/I4J8R1
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#define MAXLINE 256
#define PORT 7777
void sys_err(char *msg){
perror(msg);
exit(-1);
}
int main(int argc , char **argv){
</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> sockFd,n;
</span><span style="color: #0000ff;">char</span><span style="color: #000000;"> recvLine[MAXLINE];
</span><span style="color: #0000ff;">struct</span><span style="color: #000000;"> sockaddr_in servAddr;
</span><span style="color: #0000ff;">if</span> (argc != <span style="color: #800080;">2</span><span style="color: #000000;">) {
sys_err(</span><span style="color: #800000;">"</span><span style="color: #800000;">usage: a.out <IPaddress></span><span style="color: #800000;">"</span><span style="color: #000000;">);
}
sockFd</span>=socket(AF_INET,SOCK_STREAM,<span style="color: #800080;">0</span><span style="color: #000000;">);
memset(</span>&servAddr,<span style="color: #800080;">0</span>,<span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(servAddr));
servAddr.sin_family </span>=<span style="color: #000000;"> AF_INET;
servAddr.sin_port </span>=<span style="color: #000000;"> htons(PORT);
</span><span style="color: #0000ff;">if</span> (inet_pton(AF_INET,argv[<span style="color: #800080;">1</span>],&servAddr.sin_addr) <= <span style="color: #800080;">0</span><span style="color: #000000;">) {
sys_err(</span><span style="color: #800000;">"</span><span style="color: #800000;">inet_pton error</span><span style="color: #800000;">"</span><span style="color: #000000;">);
}
connect(sockFd,(</span><span style="color: #0000ff;">struct</span> sockaddr *)&servAddr,<span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(servAddr));
</span><span style="color: #0000ff;">while</span>((n=read(sockFd,recvLine,MAXLINE)) ><span style="color: #800080;">0</span><span style="color: #000000;"> ){
recvLine[n] </span>= <span style="color: #800000;">'</span><span style="color: #800000;">