2021-2022-1-diocs-TCP/IP和网络编程

技术2021-2022-1-diocs-TCP/IP和网络编程 2021-2022-1-diocs-TCP/IP和网络编程一、任务详情
自学教材第13章,提交学习笔记(10分)
知识点归纳以及自己最有收

2021-2022-1-教区-TCP/IP和网络编程

一、任务详情

自学教材第13章,提交学习笔记(10分)

知识点归纳以及自己最有收获的内容 (3分)

问题与解决思路(2分)

实践内容与截图,代码链接(3分)

...(知识的结构化,知识的完整性等,提交markdown文档,使用openeuler系统等)(2分)

二、知识点总结

本章讨论TCP/IP和网络编程,分为两部分。第一部分讨论了TCP/IP协议及其应用,包括TCP/IP栈、IP地址、主机名、DNS、IP包和路由器。介绍了TCP/IP网络中的UDP和TCP协议、端口号和数据流。阐述了服务器-客户端计算模型和套接字编程接口。通过UDP和TCP套接字的例子演示了网络编程。第一个编程项目可以实现一对可以通过互联网执行文件操作的TCP服务器-客户端,并允许用户定义其他通信协议来可靠地传输文件内容。

本章第二部分介绍了Web和CGI编程,并对HTTP编程模型、网页和Web浏览器进行了说明。它展示了如何配置Linux HTTPD服务器来支持用户的网页、PHP和CGI编程。解释客户端和服务器端的动态网页;演示如何使用PHP和CGI创建服务器端动态网页。

1.TCP/IP协议

TCP/IP(Comer 1988,2001;RFC 1180(1991)是互联网的基础。TCP代表传输控制协议。IP代表互联网协议。目前有两个版本的IP,即IPv4和IPv6。IPv4使用32位地址,而IPv6使用128位地址。本节重点介绍IPv4,它仍然是目前使用最多的IP版本。TCP/IP的组织结构分为几个层次,通常称为TCP/IP栈。该图显示了TCP/IP的各个级别以及每个级别的代表性组件和功能。

进程和主机之间传输层或传输层以上的数据传输只是逻辑传输。实际的数据传输发生在互联网(IP)和链路层,它们将数据包分成数据帧,以便在物理网络之间传输。下图显示了TCP/IP网络中的数据流路径。

2.IP主机和IP地址

IP地址分为两部分,即 NetworkID 字段和HostID字段.根据分类,IP地址分为A~E类。例如,一个B类IP地址被分成一个16位的网络标识,其中前两位是10,后面是一个16位的主机标识字段。发往IP地址的数据包首先发送到具有相同网络标识的路由器。路由器将通过主机标识将数据包转发到网络中的特定主机。每台主机都有一个本地主机名localhost,默认的IP地址是127.0.0.1。本地主机的链路层是一个环回虚拟设备,它将每个数据包路由回同一个本地主机。这个特性允许我们在同一台计算机上运行TCP/IP应用程序,而无需实际连接到互联网。

3.IP协议

IP协议用于在IP主机之间发送/接收数据包。IP尽可能努力工作。IP主机只向接收主机发送数据包,但不能保证数据包会发送到目的地,也不能保证按顺序发送。这意味着IP不是一个可靠的协议。必要时,必须在IP层以上实现可靠性。下图显示了IP报头格式:

4.UDP/TCP

UDP(用户数据报协议)(RFC 768 1980;Comer 1988)运行在IP上,用于发送/接收数据报。和IP类似,UDP虽然不能保证可靠性,但是快速高效。当可靠性不重要时,可以使用它。

TCP(传输控制协议)是一个面向连接的协议,用于发送/接收数据流。TCP也可以在IP上运行,但它保证了可靠的数据传输。一般来说,UDP类似于USPS发送邮件,而TCP类似于电话连接。

5.端口编号

应用程序 =(主机 IP,协议,端口号)

其中协议是TCP或UDP,端口号是分配给应用程序的唯一无符号短整数。要使用UDP或TCP,应用程序(进程)必须首先选择或获取端口号。前1024个端口号已被保留。其他端口号可供一般使用。应用程序可以选择一个可用的端口号,或者让操作系统内核分配端口号。下图显示了一些在传输层使用TCP的应用程序及其默认端口号。

6.TCP/Ip网络中的数据流

在图中,应用层的数据被传输到传输层,传输层在数据中添加一个TCP或UDP报头,以识别所使用的传输协议。合并后的数据被传输到IP网络层,并添加一个包含IP地址的IP报头来标识发送和接收主机。然后,合并的数据被传送到网络链路层,网络链路层将会计数

据分成多个帧,并添加发送和接收网络的地址,用于在物理网络之间传输。IP地址到网络地址的映射由地址解析协议(ARP)执行(ARP1982)。在接收端,数据编码过程是相反的。每一层通过剥离数据头来解包接收到的数据、重新组装数据并将数据传递到上一层。发送主机上的应用程序原始数据最终会被传递到接收主机上的相应应用程序。

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
);

在套接字地址结构中,
● TCP/IP 网络的 sin_family 始终设置为 AF_INET。

● sin_port包含按网络字节顺序排列的端口号。

●sin addr是按网络字节顺序排列的主机IP地址。

(2)套接字API

服务器必须创建一个套接字,并将其与包含服务器IP 地址和端口号的套接字地址绑定。它可以使用一个固定端口号,或者让操作系统内核选择一个端口号(如果 sin port为0)。为了与服务器通信,客户机必须创建一个套接字。对于UPD套接字,可以将套接字绑定到服务器地址。如果套接字没有绑定到任何特定的服务器,那么它必须在后续的 sendto()/recvfrom()调用中提供一个包含服务器IP 和端口号的套接字地址。

(3)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);

(4)通用套接字地址结构

通用套接字地址结构:sockaddr

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.字节排序函数

小端和大端(内存中存储两个字节有两种方法)

小端(little-endian):将低序字节存储在起始地址

大端(big-endian):将高序字节存储在起始地址

主机字节序:某个给定系统所用的字节序

输出字节序的程序:

#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]==1un.c[1]==2)
            printf("big-endian\n");
    else if (un.c[0]==2un.c[1]==1)
            printf("little-endian\n");
    else
            printf("unknown\n");
}else
      printf("sizeof(short)=%d\n",sizeof(short));
exit(0);
}

9.字节操纵函数

bzero:bzero把目标字节串指定数目的字节置为0。我们常用该函数把一个套接字地址结构初始化为0.

bocpy:指定数目的字节从源字节串移动到目标字节串。

bcmp:比较两个任意的字节串,若相同返回值为0,否则返回值为非0.

memset:把目标字节串指定数目的字节置为c。

mencmp:比较两个任意的字符串,若相同为0,否则返回一个非0值,是大于0还是小于0则取决于第一个不等的字节。

支持IPv4的inet_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编程

万维网(WWW)或 Web 是互联网上的资源和用户组合,它使用超文本传输协议(HTTP)(RFC2616 1999)进行信息交换。自 20世纪 90年代初问世以来,随着互联网能力的不断扩展,Web 已经成为世界各地人们日常生活中不可或缺的一部分。因此,对于计算机科学的学生来说,了解这项技术非常重要。在本节中,我们将介绍 HTTP和Web编程的基础知识。Web 编程通常包括Web开发中涉及的编写、标记和编码,其中包括Web 内容、Web 客户机和服务器脚本以及网络安全。狭义上,Web编程指的是创建和维护 Web 页面。Web编程中最常用的语言是HTML、XHTML、JavaScript、Perl5和 PHP。

Http编程模型

HTTP是一种基于服务器-客户机的协议,用于互联网上的应用程序。它在TCP上运行,因为它需要可靠的文件传输。图13.10所示为HTTP编程模型。

在HTTP 中,客户机可发出多个URL,将请求发送到不同的HTTP服务器。客户机与特定服务器保持永久连接不但没有必要,也不可取。客户机连接到服务器只是为了发送请求,发送完毕后会关闭连接。同样,服务器连接到客户机也只是为了发送应答,发送完毕后会再次关闭连接。每个请求或应答都需要一个单独的连接。这意味着 HTTP是一种无状态协议,因为在连续的请求或应答之间不需要维护任何信息。自然,这将导致大量系统开销和效率低下。为弥补这一缺乏状态信息的问题,HTTP 服务器和客户机可使用 cookie 来提供和维护它们之间的一些状态信息。

Web界面

Web 页面是用HTML标记语言编写的文件。Web文件通过一系列HTML元素指定Web 页面的布局,可在 Web 浏览器上解释和显示。常用的Web 浏览器有Internet Explorer、Firefox、Google Chrome 等。创建 Web 页面相当于使用HTML 元素作为构建块创建文本文件。与其说它是编程,不如说是文书类工作。因此,我们不讨论如何创建Web 页面。相反,我们将只使用一个示例 HTML文件来说明Web 页面的本质。下面给出了一个简单的HTML Web 文件。

CGI编程

CGI代表通用网关接口(RFC 3875 2004)。它是一种协议,允许 Web服务器执行程序,根据用户输入动态生成Web 页面。使用CGI.Web 服务器不必维护数百万个静态Web 页面文件来满足客户机请求。相反,它通过动态生成Web 页面来满足客户机请求。图13.14显示了CGI编程模型。

在 CGI编程模型中,客户机发送一个请求,该请求通常是一个HTML表单,包含供服务器执行的 CGI程序的输入和名称。在接收到请求后,httpd服务器会派生一个子进程来执行 CGI程序。CGI程序可以使用用户输入来查询数据库系统,如 MySQL,从而根据用户输入生成 HTML 文件。当子进程结束时,httpd服务器将生成的HTML 文件发送回客户机。CGI 程序可用任何编程语言编写,如 C语言、sh 脚本和Perl。

四、实践内容(截图、代码链接)

代码链接:

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){

/spanspan style="color: #0000ff;"int/spanspan style="color: #000000;" sockFd,n;
/spanspan style="color: #0000ff;"char/spanspan style="color: #000000;" recvLine[MAXLINE];
/spanspan style="color: #0000ff;"struct/spanspan style="color: #000000;" sockaddr_in servAddr;
/spanspan style="color: #0000ff;"if/span (argc != span style="color: #800080;"2/spanspan style="color: #000000;") {
    sys_err(/spanspan style="color: #800000;""/spanspan style="color: #800000;"usage: a.out lt;IPaddressgt;/spanspan style="color: #800000;""/spanspan style="color: #000000;");
}
sockFd/span=socket(AF_INET,SOCK_STREAM,span style="color: #800080;"0/spanspan style="color: #000000;");
memset(/spanamp;servAddr,span style="color: #800080;"0/span,span style="color: #0000ff;"sizeof/spanspan style="color: #000000;"(servAddr));
servAddr.sin_family /span=span style="color: #000000;" AF_INET;
servAddr.sin_port /span=span style="color: #000000;" htons(PORT);
/spanspan style="color: #0000ff;"if/span (inet_pton(AF_INET,argv[span style="color: #800080;"1/span],amp;servAddr.sin_addr) lt;= span style="color: #800080;"0/spanspan style="color: #000000;") {
    sys_err(/spanspan style="color: #800000;""/spanspan style="color: #800000;"inet_pton error/spanspan style="color: #800000;""/spanspan style="color: #000000;");
}
connect(sockFd,(/spanspan style="color: #0000ff;"struct/span sockaddr *)amp;servAddr,span style="color: #0000ff;"sizeof/spanspan style="color: #000000;"(servAddr));
/spanspan style="color: #0000ff;"while/span((n=read(sockFd,recvLine,MAXLINE)) gt;span style="color: #800080;"0/spanspan style="color: #000000;" ){
    recvLine[n] /span= span style="color: #800000;"'/spanspan style="color: #800000;"\0/spanspan style="color: #800000;"'/spanspan style="color: #000000;";
    /spanspan style="color: #0000ff;"if/span(fputs(recvLine,stdout) ==span style="color: #000000;" EOF){
        sys_err(/spanspan style="color: #800000;""/spanspan style="color: #800000;"fputs error/spanspan style="color: #800000;""/spanspan style="color: #000000;");
    }
}
/spanspan style="color: #0000ff;"if/span(n lt;span style="color: #800080;"0/spanspan style="color: #000000;"){
    sys_err(/spanspan style="color: #800000;""/spanspan style="color: #800000;"read error/spanspan style="color: #800000;""/spanspan style="color: #000000;");
}
/spanspan style="color: #0000ff;"return/span span style="color: #800080;"0/spanspan style="color: #000000;";

}

代码运行截图:

五、问题与解决思路

Linux系统下进行套接字编程中存在五大隐患都有什么

隐患 1.忽略返回状态

第一个隐患很明显,但它是开发新手最容易犯的一个错误。如果您忽略函数的返回状态,当它们失败或部分成功的时候,您也许会迷失。反过来,这可能传播错误,使定位问题的源头变得困难。

捕获并检查每一个返回状态,而不是忽略它们。考虑清单 1 显示的例子,一个套接字 send 函数。

1. 忽略 API 函数返回状态

int status, sock, mode;

  / Create a new stream (TCP) socket /sock =

  socket( AF_INET, SOCK_STREAM, 0 );

  ...status = send( sock, buffer, buflen, MSG_DONTWAIT );

  if (status == -1) {/ send failed /printf( "send failed: %s\n",

  strerror(errno) );

  } else {/ send succeeded -- or did it /}

清单 1 探究一个函数片断,它完成套接字 send 操作(通过套接字发送数据)。函数的错误状态被捕获并测试,但这个例子忽略了 send 在无阻塞模式(由 MSG_DONTWAIT 标志启用)下的一个特性。

send API 函数有三类可能的返回值:如果数据成功地排到传输队列,则返回 0。 如果排队失败,则返回 -1(通过使用 errno 变量可以了解失败的原因)。 如果不是所有的字符都能够在函数调用时排队,则最终的返回值是发送的字符数。

由于 send 的 MSG_DONTWAIT 变量的无阻塞性质,函数调用在发送完所有的数据、一些数据或没有发送任何数据后返回。在这里忽略返回状态将导致不完全的发送和随后的数据丢失。

隐患 2.对等套接字闭包

UNIX 有趣的一面是您几乎可以把任何东西看成是一个文件。文件本身、目录、管道、设备和套接字都被当作文件。这是新颖的抽象,意味着一整套的 API 可以用在广泛的设备类型上。

考虑 read API 函数,它从文件读取一定数量的字节。read 函数返回读取的字节数(最高为您指定的最大值);或者 -1,表示错误;或者 0,如果已经到达文件末尾。

如果在一个套接字上完成一个 read 操作并得到一个为 0 的返回值,这表明远程套接字端的对等层调用了 close API 方法。该指示与文件读取相同 —— 没有多余的数据可以通过描述符读取(参见 清单 2)。

2.适当处理 read API 函数的返回值

 int sock, status;sock = socket( AF_INET, SOCK_STREAM, 0 );

  ...status = read( sock, buffer, buflen );

  if (status 0) {/ Data read from the socket /} else if (status == -1)

  {/ Error, check errno, take action... /} else if (status ==

  0) {/ Peer closed the socket, finish the close /close( sock );

  / Further processing... /}

同样,可以用 write API 函数来探测对等套接字的闭包。在这种情况下,接收 SIGPIPE 信号,或如果该信号阻塞,write 函数将返回 -1 并设置 errno 为 EPIPE。

隐患 3.地址使用错误(EADDRINUSE)

3.使用 SO_REUSEADDR 套接字选项避免地址使用错误

  int sock, ret, on;struct sockaddr_in servaddr;

  / Create a new stream (TCP) socket /sock =

  socket( AF_INET, SOCK_STREAM, 0 ):

  / Enable address reuse /on = 1;

  ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR,

  on, sizeof(on) );/* Allow connections to

  port 8080 from any available interface

  */memset( servaddr, 0, sizeof(servaddr) );

  servaddr.sin_family = AF_INET;

  servaddr.sin_addr.s_addr = htonl( INADDR_ANY );

  servaddr.sin_port = htons( 45000 );

  /* Bind to the address (interface/port)

  */ret = bind( sock, (struct sockaddr *)servaddr, sizeof(servaddr) );

在应用了 SO_REUSEADDR 选项之后,bind API 函数将允许地址的立即重用。

隐患 4.发送结构化数据

套接字是发送无结构二进制字节流或 ASCII 数据流(比如 HTTP 上的 HTTP 页面,或 SMTP 上的电子邮件)的完美工具。但是如果试图在一个套接字上发送二进制数据,事情将会变得更加复杂。

比如说,您想要发送一个整数:您可以肯定,接收者将使用同样的方式来解释该整数吗运行在同一架构上的应用程序可以依赖它们共同的平台来对该类型的数据做出相同的解释。但是,如果一个运行在高位优先的 IBM PowerPC 上的客户端发送一个 32 位的整数到一个低位优先的 Intel x86,那将会发生什么呢字节排列将引起不正确的解释。

隐患 5.TCP 中的帧同步假定

TCP 不提供帧同步,这使得它对于面向字节流的协议是完美的。这是 TCP 与 UDP(User Datagram Protocol,用户数据报协议)的一个重要区别。UDP 是面向消息的协议,它保留发送者和接收者之间的消息边界。TCP 是一个面向流的协议,它假定正在通信的数据是无结构的。

5.tcpdump 工具的用法模式

  Display all traffic on the eth0 interface for

  the local host$ tcpdump -l -i eth0Show all traffic

  on the network coming from or going

  to host plato$ tcpdump host platoShow all HTTP traffic

  for host camus$ tcpdump host camus and (port http)View

  traffic coming from or going

  to TCP port 45000 on the local host$ tcpdump tcp port 45000

tcpdump 和 tcpflow 工具有大量的选项,包括创建复杂过滤表达式的能力。查阅下面的 参考资料 获取更多关于这些工具的信息。

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/112510.html

(0)

相关推荐

  • 蒙鸠,蒙鸠与射干告诉我们什么道理

    技术蒙鸠,蒙鸠与射干告诉我们什么道理“蒙鸠与射干”的故事:南方有鸟焉蒙鸠,名曰蒙鸠,以羽为巢,而编之以发,系之苇苕,风至苕折,卵破子死。巢非不完也,所系者然也。西方有木焉,名曰射干,茎长四寸,生于高山之上,而临百仞之渊,

    生活 2021年10月29日
  • 向心力公式,向心力和向心加速度的计算公式

    技术向心力公式,向心力和向心加速度的计算公式向心力:F=Mω²r v为线速度 单位m/s,ω为角速度 单位rad/s,m为物体质量 单位kg,r为物体的运动半径 单位m向心力公式。 向心加速度: a(n)=V²/r a(

    生活 2021年10月20日
  • 【python】使用Django搭建一个简易的web服务器

    技术【python】使用Django搭建一个简易的web服务器 【python】使用Django搭建一个简易的web服务器前言
    【玛卡巴卡】需要搭建一个接受文件的服务器,现在尝试用Django一步一步实

    礼包 2021年11月26日
  • 3元一万粉抖音自助网站,抖音刷赞的重要性!

    技术3元一万粉抖音自助网站,抖音刷赞的重要性!在抖音上发布作品,没有人点赞是一件很尴尬的事情,就相当于你的作品已经被抖音抛弃了。想要抖音点赞,可以寻找代刷抖音点赞的网址,抖音刷赞网址靠谱的有吗?这里推荐一个给大家,就这个

    测评 2021年10月26日
  • 怎么定时清理linux某些文件

    技术怎么定时清理linux某些文件这篇文章主要讲解了“怎么定时清理linux某些文件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么定时清理linux某些文件”吧!方法

    攻略 2021年11月30日
  • Access数据库操作语句有哪些

    技术Access数据库操作语句有哪些本篇文章为大家展示了Access数据库操作语句有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Access数据库操作语句简介下面我就简单介

    攻略 2021年11月23日