精华内容
下载资源
问答
  • 语法学得挺溜,校招要求写“银行家算法”的实现,却一点也写不出来? 培训班突击四个月匆匆上岗,自己独立上手做项目,写的代码全是Bug? 干了两年程序员,每遇到新技术,明明大家水平差不多,总不如其他同事学得快?
  • 计算机网络高级软件编程技术一书相配套的源代码,里面有经典的IP包流量分析、Tracert程序、TCP/UDP数据包发送、Web Server程序等等。希望对初学者有所帮助。
  • 计算机网络编程知识总结

    千次阅读 2017-12-17 21:36:24
    ...1. 网络层次划分 2. OSI七层网络模型 3. IP地址 4. 子网掩码及网络划分 5. ARP/RARP协议 6. 路由选择协议 7. TCP/IP协议 8. UDP协议  9. DNS协议 10. NAT协议 11. DHCP协议 12. HT
    博客出处:
    http://www.cnblogs.com/maybe2030/
     
    


      计算机网络学习的核心内容就是网络协议的学习。网络协议是为计算机网络中进行数据交换而建立的规则、标准或者说是约定的集合。因为不同用户的数据终端可能采取的字符集是不同的,两者需要进行通信,必须要在一定的标准上进行。一个很形象地比喻就是我们的语言,我们大天朝地广人多,地方性语言也非常丰富,而且方言之间差距巨大。A地区的方言可能B地区的人根本无法接受,所以我们要为全国人名进行沟通建立一个语言标准,这就是我们的普通话的作用。同样,放眼全球,我们与外国友人沟通的标准语言是英语,所以我们才要苦逼的学习英语。

      计算机网络协议同我们的语言一样,多种多样。而ARPA公司与1977年到1979年推出了一种名为ARPANET的网络协议受到了广泛的热捧,其中最主要的原因就是它推出了人尽皆知的TCP/IP标准网络协议。目前TCP/IP协议已经成为Internet中的“通用语言”,下图为不同计算机群之间利用TCP/IP进行通信的示意图。

    1. 网络层次划分

      为了使不同计算机厂家生产的计算机能够相互通信,以便在更大的范围内建立计算机网络,国际标准化组织(ISO)在1978年提出了“开放系统互联参考模型”,即著名的OSI/RM模型(Open System Interconnection/Reference Model)。它将计算机网络体系结构的通信协议划分为七层,自下而上依次为:物理层(Physics Layer)、数据链路层(Data Link Layer)、网络层(Network Layer)、传输层(Transport Layer)、会话层(Session Layer)、表示层(Presentation Layer)、应用层(Application Layer)。 其中第四层完成数据传送服务,上面三层面向用户。
      除了标准的OSI七层模型以外,常见的网络层次划分还有TCP/IP四层协议以及TCP/IP五层协议,它们之间的对应关系如下图所示:
     
     

    2. OSI七层网络模型

      TCP/IP协议毫无疑问是互联网的基础协议,没有它就根本不可能上网,任何和互联网有关的操作都离不开TCP/IP协议。不管是OSI七层模型还是TCP/IP的四层、五层模型,每一层中都要自己的专属协议,完成自己相应的工作以及与上下层级之间进行沟通。由于OSI七层模型为网络的标准层次划分,所以我们以OSI七层模型为例从下向上进行一一介绍。
     
      1)物理层(Physical Layer)

      激活、维持、关闭通信端点之间的机械特性、电气特性、功能特性以及过程特性。该层为上层协议提供了一个传输数据的可靠的物理媒体。简单的说,物理层确保原始的数据可在各种物理媒体上传输。物理层记住两个重要的设备名称,中继器(Repeater,也叫放大器)和集线器。

      2)数据链路层(Data Link Layer)

      数据链路层在物理层提供的服务的基础上向网络层提供服务,其最基本的服务是将源自网络层来的数据可靠地传输到相邻节点的目标机网络层。为达到这一目的,数据链路必须具备一系列相应的功能,主要有:如何将数据组合成数据块,在数据链路层中称这种数据块为帧(frame),帧是数据链路层的传送单位;如何控制帧在物理信道上的传输,包括如何处理传输差错,如何调节发送速率以使与接收方相匹配;以及在两个网络实体之间提供数据链路通路的建立、维持和释放的管理。数据链路层在不可靠的物理介质上提供可靠的传输。该层的作用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。

      有关数据链路层的重要知识点:

      1> 数据链路层为网络层提供可靠的数据传输;

      2> 基本数据单位为帧;

      3> 主要的协议:以太网协议;

      4> 两个重要设备名称:网桥和交换机。

      3)网络层(Network Layer)

      网络层的目的是实现两个端系统之间的数据透明传送,具体功能包括寻址和路由选择、连接的建立、保持和终止等。它提供的服务使传输层不需要了解网络中的数据传输和交换技术。如果您想用尽量少的词来记住网络层,那就是“路径选择、路由及逻辑寻址”。

      网络层中涉及众多的协议,其中包括最重要的协议,也是TCP/IP的核心协议——IP协议。IP协议非常简单,仅仅提供不可靠、无连接的传送服务。IP协议的主要功能有:无连接数据报传输、数据报路由选择和差错控制。与IP协议配套使用实现其功能的还有地址解析协议ARP、逆地址解析协议RARP、因特网报文协议ICMP、因特网组管理协议IGMP。具体的协议我们会在接下来的部分进行总结,有关网络层的重点为:

      1> 网络层负责对子网间的数据包进行路由选择。此外,网络层还可以实现拥塞控制、网际互连等功能;

      2> 基本数据单位为IP数据报;

      3> 包含的主要协议:

      IP协议(Internet Protocol,因特网互联协议);

      ICMP协议(Internet Control Message Protocol,因特网控制报文协议);

      ARP协议(Address Resolution Protocol,地址解析协议);

      RARP协议(Reverse Address Resolution Protocol,逆地址解析协议)。

      4> 重要的设备:路由器。

      4)传输层(Transport Layer)

      第一个端到端,即主机到主机的层次。传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输。此外,传输层还要处理端到端的差错控制和流量控制问题。

      传输层的任务是根据通信子网的特性,最佳的利用网络资源,为两个端系统的会话层之间,提供建立、维护和取消传输连接的功能,负责端到端的可靠数据传输。在这一层,信息传送的协议数据单元称为段或报文。
      网络层只是根据网络地址将源结点发出的数据包传送到目的结点,而传输层则负责将数据可靠地传送到相应的端口。
      有关网络层的重点:
      1> 传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输以及端到端的差错控制和流量控制问题;
      2> 包含的主要协议:TCP协议(Transmission Control Protocol,传输控制协议)、UDP协议(User Datagram Protocol,用户数据报协议);
      3> 重要设备:网关。

      5)会话层

      会话层管理主机之间的会话进程,即负责建立、管理、终止进程之间的会话。会话层还利用在数据中插入校验点来实现数据的同步。

      6)表示层

      表示层对上层数据或信息进行变换以保证一个主机应用层信息可以被另一个主机的应用程序理解。表示层的数据转换包括数据的加密、压缩、格式转换等。

      7)应用层

      为操作系统或网络应用程序提供访问网络服务的接口。

      会话层、表示层和应用层重点:

      1> 数据传输基本单位为报文;

      2> 包含的主要协议:FTP(文件传送协议)、Telnet(远程登录协议)、DNS(域名解析协议)、SMTP(邮件传送协议),POP3协议(邮局协议),HTTP协议(Hyper Text Transfer Protocol)。

    3. IP地址

      1)网络地址

      IP地址由网络号(包括子网号)和主机号组成,网络地址的主机号为全0,网络地址代表着整个网络。

      2)广播地址

      广播地址通常称为直接广播地址,是为了区分受限广播地址。

      广播地址与网络地址的主机号正好相反,广播地址中,主机号为全1。当向某个网络的广播地址发送消息时,该网络内的所有主机都能收到该广播消息。

      3)组播地址

      D类地址就是组播地址。

      先回忆下A,B,C,D类地址吧:

      A类地址以0开头,第一个字节作为网络号,地址范围为:0.0.0.0~127.255.255.255;(modified @2016.05.31)

      B类地址以10开头,前两个字节作为网络号,地址范围是:128.0.0.0~191.255.255.255;

      C类地址以110开头,前三个字节作为网络号,地址范围是:192.0.0.0~223.255.255.255。

      D类地址以1110开头,地址范围是224.0.0.0~239.255.255.255,D类地址作为组播地址(一对多的通信);

      E类地址以1111开头,地址范围是240.0.0.0~255.255.255.255,E类地址为保留地址,供以后使用。

      注:只有A,B,C有网络号和主机号之分,D类地址和E类地址没有划分网络号和主机号。

      4)255.255.255.255

      该IP地址指的是受限的广播地址。受限广播地址与一般广播地址(直接广播地址)的区别在于,受限广播地址只能用于本地网络,路由器不会转发以受限广播地址为目的地址的分组;一般广播地址既可在本地广播,也可跨网段广播。例如:主机192.168.1.1/30上的直接广播数据包后,另外一个网段192.168.1.5/30也能收到该数据报;若发送受限广播数据报,则不能收到。

      注:一般的广播地址(直接广播地址)能够通过某些路由器(当然不是所有的路由器),而受限的广播地址不能通过路由器。

      5)0.0.0.0

      常用于寻找自己的IP地址,例如在我们的RARP,BOOTP和DHCP协议中,若某个未知IP地址的无盘机想要知道自己的IP地址,它就以255.255.255.255为目的地址,向本地范围(具体而言是被各个路由器屏蔽的范围内)的服务器发送IP请求分组。

      6)回环地址

      127.0.0.0/8被用作回环地址,回环地址表示本机的地址,常用于对本机的测试,用的最多的是127.0.0.1。

      7)A、B、C类私有地址

      私有地址(private address)也叫专用地址,它们不会在全球使用,只具有本地意义。

      A类私有地址:10.0.0.0/8,范围是:10.0.0.0~10.255.255.255

      B类私有地址:172.16.0.0/12,范围是:172.16.0.0~172.31.255.255

      C类私有地址:192.168.0.0/16,范围是:192.168.0.0~192.168.255.255

    4. 子网掩码及网络划分

      随着互连网应用的不断扩大,原先的IPv4的弊端也逐渐暴露出来,即网络号占位太多,而主机号位太少,所以其能提供的主机地址也越来越稀缺,目前除了使用NAT在企业内部利用保留地址自行分配以外,通常都对一个高类别的IP地址进行再划分,以形成多个子网,提供给不同规模的用户群使用。

      这里主要是为了在网络分段情况下有效地利用IP地址,通过对主机号的高位部分取作为子网号,从通常的网络位界限中扩展或压缩子网掩码,用来创建某类地址的更多子网。但创建更多的子网时,在每个子网上的可用主机地址数目会比原先减少。

      什么是子网掩码?

      子网掩码是标志两个IP地址是否同属于一个子网的,也是32位二进制地址,其每一个为1代表该位是网络位,为0代表主机位。它和IP地址一样也是使用点式十进制来表示的。如果两个IP地址在子网掩码的按位与的计算下所得结果相同,即表明它们共属于同一子网中。

      在计算子网掩码时,我们要注意IP地址中的保留地址,即“ 0”地址和广播地址,它们是指主机地址或网络地址全为“ 0”或“ 1”时的IP地址,它们代表着本网络地址和广播地址,一般是不能被计算在内的。

      子网掩码的计算:

      对于无须再划分成子网的IP地址来说,其子网掩码非常简单,即按照其定义即可写出:如某B类IP地址为 10.12.3.0,无须再分割子网,则该IP地址的子网掩码255.255.0.0。如果它是一个C类地址,则其子网掩码为 255.255.255.0。其它类推,不再详述。下面我们关键要介绍的是一个IP地址,还需要将其高位主机位再作为划分出的子网网络号,剩下的是每个子网的主机号,这时该如何进行每个子网的掩码计算。

      下面总结一下有关子网掩码和网络划分常见的面试考题:

      1)利用子网数来计算

      在求子网掩码之前必须先搞清楚要划分的子网数目,以及每个子网内的所需主机数目。

      (1) 将子网数目转化为二进制来表示;

      如欲将B类IP地址168.195.0.0划分成27个子网:27=11011;

      (2) 取得该二进制的位数,为N;

      该二进制为五位数,N = 5

      (3) 取得该IP地址的类子网掩码,将其主机地址部分的的前N位置1即得出该IP地址划分子网的子网掩码。

      将B类地址的子网掩码255.255.0.0的主机地址前5位置 1,得到 255.255.248.0

      2)利用主机数来计算

      如欲将B类IP地址168.195.0.0划分成若干子网,每个子网内有主机700台:

      (1) 将主机数目转化为二进制来表示;

      700=1010111100;

      (2) 如果主机数小于或等于254(注意去掉保留的两个IP地址),则取得该主机的二进制位数,为N,这里肯定 N<8。如果大于254,则 N>8,这就是说主机地址将占据不止8位;

      该二进制为十位数,N=10;

      (3) 使用255.255.255.255来将该类IP地址的主机地址位数全部置1,然后从后向前的将N位全部置为 0,即为子网掩码值。

      将该B类地址的子网掩码255.255.0.0的主机地址全部置1,得到255.255.255.255,然后再从后向前将后 10位置0,即为:11111111.11111111.11111100.00000000,即255.255.252.0。这就是该欲划分成主机为700台的B类IP地址 168.195.0.0的子网掩码。

      3)还有一种题型,要你根据每个网络的主机数量进行子网地址的规划和计算子网掩码。这也可按上述原则进行计算。

      比如一个子网有10台主机,那么对于这个子网需要的IP地址是:

      10+1+1+1=13

      注意:加的第一个1是指这个网络连接时所需的网关地址,接着的两个1分别是指网络地址和广播地址。

      因为13小于16(16等于2的4次方),所以主机位为4位。而256-16=240,所以该子网掩码为255.255.255.240。

      如果一个子网有14台主机,不少人常犯的错误是:依然分配具有16个地址空间的子网,而忘记了给网关分配地址。这样就错误了,因为14+1+1+1=1717大于16,所以我们只能分配具有32个地址(32等于2的5次方)空间的子网。这时子网掩码为:255.255.255.224。

    5. ARP/RARP协议

      地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。地址解析协议是建立在网络中各个主机互相信任的基础上的,网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其记入本机ARP缓存;由此攻击者就可以向某一主机发送伪ARP应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个ARP欺骗。ARP命令可用于查询本机ARP缓存中IP地址和MAC地址的对应关系、添加或删除静态对应关系等。

      ARP工作流程举例:

      主机A的IP地址为192.168.1.1,MAC地址为0A-11-22-33-44-01;
      主机B的IP地址为192.168.1.2,MAC地址为0A-11-22-33-44-02;
      当主机A要与主机B通信时,地址解析协议可以将主机B的IP地址(192.168.1.2)解析成主机B的MAC地址,以下为工作流程:
      (1)根据主机A上的路由表内容,IP确定用于访问主机B的转发IP地址是192.168.1.2。然后A主机在自己的本地ARP缓存中检查主机B的匹配MAC地址。
      (2)如果主机A在ARP缓存中没有找到映射,它将询问192.168.1.2的硬件地址,从而将ARP请求帧广播到本地网络上的所有主机。源主机A的IP地址和MAC地址都包括在ARP请求中。本地网络上的每台主机都接收到ARP请求并且检查是否与自己的IP地址匹配。如果主机发现请求的IP地址与自己的IP地址不匹配,它将丢弃ARP请求。
      (3)主机B确定ARP请求中的IP地址与自己的IP地址匹配,则将主机A的IP地址和MAC地址映射添加到本地ARP缓存中。
      (4)主机B将包含其MAC地址的ARP回复消息直接发送回主机A。
      (5)当主机A收到从主机B发来的ARP回复消息时,会用主机B的IP和MAC地址映射更新ARP缓存。本机缓存是有生存期的,生存期结束后,将再次重复上面的过程。主机B的MAC地址一旦确定,主机A就能向主机B发送IP通信了。

      逆地址解析协议,即RARP,功能和ARP协议相对,其将局域网中某个主机的物理地址转换为IP地址,比如局域网中有一台主机只知道物理地址而不知道IP地址,那么可以通过RARP协议发出征求自身IP地址的广播请求,然后由RARP服务器负责回答。

      RARP协议工作流程:

      (1)给主机发送一个本地的RARP广播,在此广播包中,声明自己的MAC地址并且请求任何收到此请求的RARP服务器分配一个IP地址;

      (2)本地网段上的RARP服务器收到此请求后,检查其RARP列表,查找该MAC地址对应的IP地址;

      (3)如果存在,RARP服务器就给源主机发送一个响应数据包并将此IP地址提供给对方主机使用;
      (4)如果不存在,RARP服务器对此不做任何的响应;
      (5)源主机收到从RARP服务器的响应信息,就利用得到的IP地址进行通讯;如果一直没有收到RARP服务器的响应信息,表示初始化失败。

    6. 路由选择协议

      常见的路由选择协议有:RIP协议、OSPF协议。

      RIP协议 :底层是贝尔曼福特算法,它选择路由的度量标准(metric)是跳数,最大跳数是15跳,如果大于15跳,它就会丢弃数据包。

      OSPF协议 :Open Shortest Path First开放式最短路径优先,底层是迪杰斯特拉算法,是链路状态路由选择协议,它选择路由的度量标准是带宽,延迟。

    7. TCP/IP协议

      TCP/IP协议是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。通俗而言:TCP负责发现传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。而IP是给因特网的每一台联网设备规定一个地址。
      IP层接收由更低层(网络接口层例如以太网设备驱动程序)发来的数据包,并把该数据包发送到更高层---TCP或UDP层;相反,IP层也把从TCP或UDP层接收来的数据包传送到更低层。IP数据包是不可靠的,因为IP并没有做任何事情来确认数据包是否按顺序发送的或者有没有被破坏,IP数据包中含有发送它的主机的地址(源地址)和接收它的主机的地址(目的地址)。

       TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于端到端的通讯。TCP提供的是一种可靠的数据流服务,采用“带重传的肯定确认”技术来实现传输的可靠性。TCP还采用一种称为“滑动窗口”的方式进行流量控制,所谓窗口实际表示接收能力,用以限制发送方的发送速度。

      TCP报文首部格式:

      TCP协议的三次握手和四次挥手:

     

      注:seq:"sequance"序列号;ack:"acknowledge"确认号;SYN:"synchronize"请求同步标志;;ACK:"acknowledge"确认标志";FIN:"Finally"结束标志。

      TCP连接建立过程:首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。

      TCP连接断开过程:假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

      为什么要三次挥手?

      在只有两次“握手”的情形下,假设Client想跟Server建立连接,但是却因为中途连接请求的数据报丢失了,故Client端不得不重新发送一遍;这个时候Server端仅收到一个连接请求,因此可以正常的建立连接。但是,有时候Client端重新发送请求不是因为数据报丢失了,而是有可能数据传输过程因为网络并发量很大在某结点被阻塞了,这种情形下Server端将先后收到2次请求,并持续等待两个Client请求向他发送数据...问题就在这里,Cient端实际上只有一次请求,而Server端却有2个响应,极端的情况可能由于Client端多次重新发送请求数据而导致Server端最后建立了N多个响应在等待,因而造成极大的资源浪费!所以,“三次握手”很有必要!

      为什么要四次挥手?

      试想一下,假如现在你是客户端你想断开跟Server的所有连接该怎么做?第一步,你自己先停止向Server端发送数据,并等待Server的回复。但事情还没有完,虽然你自身不往Server发送数据了,但是因为你们之前已经建立好平等的连接了,所以此时他也有主动权向你发送数据;故Server端还得终止主动向你发送数据,并等待你的确认。其实,说白了就是保证双方的一个合约的完整执行!

      使用TCP的协议:FTP(文件传输协议)、Telnet(远程登录协议)、SMTP(简单邮件传输协议)、POP3(和SMTP相对,用于接收邮件)、HTTP协议等。

    8. UDP协议 

      UDP用户数据报协议,是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。 UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编程验证。
       UDP与TCP位于同一层,但它不管数据包的顺序、错误或重发。因此,UDP不被应用于那些使用虚电路的面向连接的服务,UDP主要用于那些面向查询---应答的服务,例如NFS。相对于FTP或Telnet,这些服务需要交换的信息量较小。
      每个UDP报文分UDP报头和UDP数据区两部分。报头由四个16位长(2字节)字段组成,分别说明该报文的源端口、目的端口、报文长度以及校验值。UDP报头由4个域组成,其中每个域各占用2个字节,具体如下:
      (1)源端口号;
      (2)目标端口号;
      (3)数据报长度;
      (4)校验值。
      使用UDP协议包括:TFTP(简单文件传输协议)、SNMP(简单网络管理协议)、DNS(域名解析协议) NFS、 BOOTP。
       TCP 与 UDP 的区别:TCP是面向连接的,可靠的字节流服务;UDP是面向无连接的,不可靠的数据报服务。

    9. DNS协议

      DNS是域名系统(DomainNameSystem)的缩写,该系统用于命名组织到域层次结构中的计算机和网络服务,可以简单地理解为将URL转换为IP地址。域名是由圆点分开一串单词或缩写组成的,每一个域名都对应一个惟一的IP地址,在Internet上域名与IP地址之间是一一对应的,DNS就是进行域名解析的服务器。DNS命名用于Internet等TCP/IP网络中,通过用户友好的名称查找计算机和服务。

    10. NAT协议

      NAT网络地址转换(Network Address Translation)属接入广域网(WAN)技术,是一种将私有(保留)地址转化为合法IP地址的转换技术,它被广泛应用于各种类型Internet接入方式和各种类型的网络中。原因很简单,NAT不仅完美地解决了lP地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。

    11. DHCP协议

      DHCP动态主机设置协议(Dynamic Host Configuration Protocol)是一个局域网的网络协议,使用UDP协议工作,主要有两个用途:给内部网络或网络服务供应商自动分配IP地址,给用户或者内部网络管理员作为对所有计算机作中央管理的手段。

    12. HTTP协议

      超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。

      HTTP 协议包括哪些请求?

      GET:请求读取由URL所标志的信息。

      POST:给服务器添加信息(如注释)。

      PUT:在给定的URL下存储一个文档。

      DELETE:删除给定的URL所标志的资源。

      HTTP 中, POST 与 GET 的区别

      1)Get是从服务器上获取数据,Post是向服务器传送数据。

      2)Get是把参数数据队列加到提交表单的Action属性所指向的URL中,值和表单内各个字段一一对应,在URL中可以看到。

      3)Get传送的数据量小,不能大于2KB;Post传送的数据量较大,一般被默认为不受限制。

      4)根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的。

      I. 所谓 安全的 意味着该操作用于获取信息而非修改信息。换句话说,GET请求一般不应产生副作用。就是说,它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。

      II. 幂等 的意味着对同一URL的多个请求应该返回同样的结果。

    13. 一个举例

      在浏览器中输入 www.baidu.com  后执行的全部过程

      现在假设如果我们在客户端(客户端)浏览器中输入http://www.baidu.com,而baidu.com为要访问的服务器(服务器),下面详细分析客户端为了访问服务器而执行的一系列关于协议的操作:

      1)客户端浏览器通过DNS解析到www.baidu.com的IP地址220.181.27.48,通过这个IP地址找到客户端到服务器的路径。客户端浏览器发起一个HTTP会话到220.161.27.48,然后通过TCP进行封装数据包,输入到网络层。

      2)在客户端的传输层,把HTTP会话请求分成报文段,添加源和目的端口,如服务器使用80端口监听客户端的请求,客户端由系统随机选择一个端口如5000,与服务器进行交换,服务器把相应的请求返回给客户端的5000端口。然后使用IP层的IP地址查找目的端。

      3)客户端的网络层不用关系应用层或者传输层的东西,主要做的是通过查找路由表确定如何到达服务器,期间可能经过多个路由器,这些都是由路由器来完成的工作,不作过多的描述,无非就是通过查找路由表决定通过那个路径到达服务器。

      4)客户端的链路层,包通过链路层发送到路由器,通过邻居协议查找给定IP地址的MAC地址,然后发送ARP请求查找目的地址,如果得到回应后就可以使用ARP的请求应答交换的IP数据包现在就可以传输了,然后发送IP数据包到达服务器的地址。


    展开全文
  • SOCKET 网络编程 计算机网络 作业 客户端 服务器端 client svever SOCKET 网络编程 计算机网络 作业 客户端 服务器端 client svever
  • 四、TCPUDP 五、地址端口号 端口号的确定 端口号与协议 六、TCP/IP介绍 6.1、TCP链接建立-三次握手 TCP的三次握手的漏洞 无效连接监视释放 延缓TCB分配方法 使用防火墙 6.2、TCP链接的释放-四次挥手...

    目录

    一、OSI七层模型

    二、TCP/IP模型

    三、TCP/IP协议族

    四、TCP和UDP

    五、地址和端口号

    端口号的确定

    端口号与协议

    六、TCP/IP介绍

    6.1、TCP链接建立-三次握手

    TCP的三次握手的漏洞

    无效连接监视释放

    延缓TCB分配方法

    使用防火墙

    6.2、TCP链接的释放-四次挥手(分手)

    6.3、TCP/IP中的数据包

    6.4、TCP的通讯原理

    Socket套接字

    TCP缓冲区

    6.5、TCP 的可靠性

    6.6、TCP中的滑动窗口

    七、UDP协议

    八、HTTP协议介绍

    8.1、URI和URL的区别

    8.2、一个完整的URL

    8.3、HTTP请求的传输过程

    一次完整http请求的过程

    8.4、HTTP 协议报文结构

    请求报文结构

    响应报文结构

     


    一、OSI七层模型

    开放系统互连参考模型 (Open System Interconnect 简称OSI)是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。其目的是为异种计算机互连提供一个共同的基础和标准框架,并为保持相关标准的一致性和兼容性提供共同的参考。这里所说的开放系统,实质上指的是遵循OSI参考模型和相关协议能够实现互连的具有各种应用目的的计算机系统。

    OSI采用了分层的结构化技术,共分七层,物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

    二、TCP/IP模型

    OSI模型比较复杂且学术化,所以我们实际使用的TCP/IP模型,共分4层,链路层、网络层、传输层、应用层。两个模型之间的对应关系如图所示:

    无论什么模型,每一个抽象层建立在低一层提供的服务上,并且为高一层提供服务。

    三、TCP/IP协议族

    Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。协议采用了4层的层级结构。然而在很多情况下,它是利用 IP 进行通信时所必须用到的协议群的统称。也就是说,它其实是个协议家族,由很多个协议组成,并且是在不同的层, 是互联网的基础通信架构。

    四、TCP和UDP

    在上述表格中,网际协议IP是TCP/IP中非常重要的协议。负责对数据加上IP地址(有发送它的主机的地址(源地址)和接收它的主机的地址(目的地址))和其他的数据以确定传输的目标。

    而TCP和UDP都是传输层的协议,传输层主要为两台主机上的应用程序提供端到端的通信。

    但是TCP和UDP最不同的地方是,TCP提供了一种可靠的数据传输服务,TCP是面向连接的,也就是说,利用TCP通信的两台主机首先要经历一个建立连接的过程,等到连接建立后才开始传输数据,而且传输过程中采用“带重传的肯定确认”技术来实现传输的可靠性。TCP还采用一种称为“滑动窗口”的方式进行流量控制,发送完成后还会关闭连接。所以TCP要比UDP可靠的多。

    UDP(User Datagram Protocol的简称, 中文名是用户数据报协议)是把数据直接发出去,而不管对方是不是在接收,也不管对方是否能接收的了,也不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编程验证。

    注意:

    我们一些常见的网络应用基本上都是基于TCP和UDP的,这两个协议又会使用网络层的IP协议。但是我们完全可以绕过传输层的TCP和UDP,直接使用IP,比如Linux中LVS,甚至直接访问链路层,比如tcpdump程序就是直接和链路层进行通信的。

    上图中,其他一些协议的名称解释,了解即可:

    ICMP  控制报文协议

    IGMP  internet组管理协议

    ARP   地址解析协议

    RARP 反向地址转化协议

    五、地址和端口号

    我们常听说 MAC 地址和 IP 地址。MAC地址就是在媒体接入层上使用的地址,也叫物理地址、硬件地址或链路地址,由网络设备制造商生产时写在硬件内部。MAC地址与网络无关,也即无论将带有这个地址的硬件(如网卡、集线器、路由器等)接入到网络的何处,都有相同的MAC地址,它由厂商写在网卡的BIOS里,从理论上讲,除非盗来硬件(网卡),否则是没有办法冒名顶替的。

    IP 地址后者用来识别 TCP/IP 网络中互连的主机和路由器。IP地址基于逻辑,比较灵活,不受硬件限制,也容易记忆。

    在传输层也有这种类似于地址的概念,那就是端口号。端口号用来识别同一台计算机中进行通信的不同应用程序。因此,它也被称为程序地址。

    一台计算机上同时可以运行多个程序。传输层协议正是利用这些端口号识别本机中正在进行通信的应用程序,并准确地将数据传输。

    端口号的确定

    •    标准既定的端口号:这种方法也叫静态方法。它是指每个应用程序都有其指定的端口号。但并不是说可以随意使用任何一个端口号。例如 HTTP、FTP、TELNET 等广为使用的应用协议中所使用的端口号就是固定的。这些端口号被称为知名端口号,分布在 0~1023 之间;除知名端口号之外,还有一些端口号被正式注册,它们分布在 1024~49151 之间,不过这些端口号可用于任何通信用途。

    •    时序分配法:服务器有必要确定监听端口号,但是接受服务的客户端没必要确定端口号。在这种方法下,客户端应用程序完全可以不用自己设置端口号,而全权交给操作系统进行分配。动态分配的端口号范围在 49152~65535 之间。

    端口号与协议

    •    端口号由其使用的传输层协议决定。因此,不同的传输层协议可以使用相同的端口号。

    •    此外,那些知名端口号与传输层协议并无关系。只要端口一致都将分配同一种应用程序进行处理。

    六、TCP/IP介绍

    TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于端到端的通讯。

    TCP提供的是一种可靠的数据流服务,采用“带重传的肯定确认”技术来实现传输的可靠性。TCP还采用一种称为“滑动窗口”的方式进行流量控制,所谓窗口实际表示接收能力,用以限制发送方的发送速度。

    如果IP数据包中有已经封好的TCP数据包,那么IP将把它们向‘上’传送到TCP层。TCP将包排序并进行错误检查,同时实现虚电路间的连接。TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。

    TCP将它的信息送到更高层的应用程序,例如Telnet的服务程序和客户程序。应用程序轮流将信息送回TCP层,TCP层便将它们向下传送到IP层,设备驱动程序和物理介质,最后到接收方。

    面向连接的服务(例如TelnetFTPrloginX WindowsSMTP)需要高度的可靠性,所以它们使用了TCP。DNS在某些情况下使用TCP(发送和接收域名数据库),但使用UDP传送有关单个主机的信息。

    6.1、TCP链接建立-三次握手

    TCP 提供面向有连接的通信传输。面向有连接是指在数据通信开始之前先做好两端之间的准备工作。

    所谓三次握手是指建立一个 TCP 连接时需要客户端和服务器端总共发送三个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发。

    第一次握手:客户端将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给服务器端,客户端进入SYN_SENT状态,等待服务器端确认。

    第二次握手:服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。

    第三次握手:客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。

    通过linux下,tcpdump可以抓包,使用wireshark可以清楚地看到TCP建立连接的过程。

    TCP的三次握手的漏洞

    但是在TCP三次握手中是有一个缺陷的,就是如果我们利用三次握手的缺陷进行攻击。这个攻击就是SYN洪泛攻击。三次握手中有一个第二次握手,服务端向客户端应道请求,应答请求是需要客户端IP的,服务端是需要知道客户端IP的,攻击者就伪造这个IP,往服务器端狂发送第一次握手的内容,当然第一次握手中的客户端IP地址是伪造的,从而服务端忙于进行第二次握手但是第二次握手当然没有结果,所以导致服务器端被拖累,死机。

    当然我们的生活中也有可能有这种例子,一个家境一般的IT男去表白他的女神被拒绝了,理由是他家里没矿,IT男为了报复,采用了洪泛攻击,他请了很多人伪装成有钱人去表白那位追求矿的女神,让女生每次想交往时发现表白的人不见了同时还联系不上了。

    面对这种攻击,有以下的解决方案,最好的方案是防火墙。

    无效连接监视释放

    这种方法不停监视所有的连接,包括三次握手的,还有握手一次的,反正是所有的,当达到一定(与)阈值时拆除这些连接,从而释放系统资源。这种方法对于所有的连接一视同仁,不管是正常的还是攻击的,所以这种方式不推荐。

    延缓TCB分配方法

    一般的做完第一次握手之后,服务器就需要为该请求分配一个TCB(连接控制资源),通常这个资源需要200多个字节。延迟TCB的分配,当正常连接建立起来后再分配TCB则可以有效地减轻服务器资源的消耗。

    使用防火墙

    防火墙在确认了连接的有效性后,才向内部的服务器(Listener)发起SYN请求,

    6.2、TCP链接的释放-四次挥手(分手)

    四次挥手即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。

    由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

    1. 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
    2. 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
    3. 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
    4. 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
    5. 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

    服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

    抓包4次分手

    6.3、TCP/IP中的数据包

    每个分层中,都会对所发送的数据附加一个首部,在这个首部中包含了该层必要的信息,如发送的目标地址以及协议相关信息。通常,为协议提供的信息为包首部,所要发送的内容为数据。在下一层的角度看,从上一层收到的包全部都被认为是本层的数据。

    网络中传输的数据包由两部分组成:一部分是协议所要用到的首部,另一部分是上一层传过来的数据。首部的结构由协议的具体规范详细定义。在数据包的首部,明确标明了协议应该如何读取数据。反过来说,看到首部,也就能够了解该协议必要的信息以及所要处理的数据。

    ① 应用程序处理
    首先应用程序会进行编码处理,这些编码相当于 OSI 的表示层功能;
    编码转化后,邮件不一定马上被发送出去,这种何时建立通信连接何时发送数据的管理功能,相当于 OSI 的会话层功能。

    ② TCP 模块的处理
    TCP 根据应用的指示,负责建立连接、发送数据以及断开连接。TCP 提供将应用层发来的数据顺利发送至对端的可靠传输。为了实现这一功能,需要在应用层数据的前端附加一个 TCP 首部。

    ③ IP 模块的处理
    IP 将 TCP 传过来的 TCP 首部和 TCP 数据合起来当做自己的数据,并在 TCP 首部的前端加上自己的 IP 首部。IP 包生成后,参考路由控制表决定接受此 IP 包的路由或主机。

     ④ 网络接口(以太网驱动)的处理
    从 IP 传过来的 IP 包对于以太网来说就是数据。给这些数据附加上以太网首部并进行发送处理,生成的以太网数据包将通过物理层传输给接收端。

    ⑤ 网络接口(以太网驱动)的处理
    主机收到以太网包后,首先从以太网包首部找到 MAC 地址判断是否为发送给自己的包,若不是则丢弃数据。
    如果是发送给自己的包,则从以太网包首部中的类型确定数据类型,再传给相应的模块,如 IP、ARP 等。这里的例子则是 IP 。

    ⑥ IP 模块的处理
    IP 模块接收到 数据后也做类似的处理。从包首部中判断此 IP 地址是否与自己的 IP 地址匹配,如果匹配则根据首部的协议类型将数据发送给对应的模块,如 TCP、UDP。这里的例子则是 TCP。
    另外吗,对于有路由器的情况,接收端地址往往不是自己的地址,此时,需要借助路由控制表,在调查应该送往的主机或路由器之后再进行转发数据。

    ⑦ TCP 模块的处理
    在 TCP 模块中,首先会计算一下校验和,判断数据是否被破坏。然后检查是否在按照序号接收数据。最后检查端口号,确定具体的应用程序。数据被完整地接收以后,会传给由端口号识别的应用程序。

    ⑧ 应用程序的处理
    接收端应用程序会直接接收发送端发送的数据。通过解析数据,展示相应的内容。

    6.4、TCP的通讯原理

    Socket套接字

    Socket 的原意是“插座”,在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。TCP用主机的IP地址加上主机上的端口号作为TCP连接的端点,这种端点就叫做套接字(socket)。

    区分不同应用程序进程间的网络通信和连接,主要有3个参数:通信的目的IP地址、使用的传输层协议(TCP或UDP)和使用的端口号。通过将这3个参数结合起来,与一个“插座”Socket绑定,应用层就可以和传输层通过套接字接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

    套接字对是一个定义该连接的两个端点的四元组:本地IP地址、本地TCP端口号、外地IP地址、外地TCP端口号。套接字对唯一标识一个网络上的每个TCP连接。

    TCP缓冲区

    每个TCP的Socket的内核中都有一个发送缓冲区和一个接收缓冲区。现在我们假设用write()方法发送数据,使用 read()方法接收数据。

    write()并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送到目标机器。一旦将数据写入到缓冲区,函数就可以成功返回,不管它们有没有到达目标机器,也不管它们何时被发送到网络,这些都是TCP协议负责的事情。

    TCP协议独立于 write()函数,数据有可能刚被写入缓冲区就发送到网络,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络,这取决于当时的网络情况、当前线程是否空闲等诸多因素,不由程序员控制。

    read()也是如此,也从输入缓冲区中读取数据,而不是直接从网络中读取。

    总得来说,I/O缓冲区在每个TCP套接字中单独存在;I/O缓冲区在创建套接字时自动生成;

    6.5、TCP 的可靠性

    在 TCP 中,当发送端的数据到达接收主机时,接收端主机会返回一个已收到消息的通知。这个消息叫做确认应答(ACK)。当发送端将数据发出之后会等待对端的确认应答。如果有确认应答,说明数据已经成功到达对端。反之,则数据丢失的可能性很大。

    在一定时间内没有等待到确认应答,发送端就可以认为数据已经丢失,并进行重发。由此,即使产生了丢包,仍然能够保证数据能够到达对端,实现可靠传输。

    未收到确认应答并不意味着数据一定丢失。也有可能是数据对方已经收到,只是返回的确认应答在途中丢失。这种情况也会导致发送端误以为数据没有到达目的地而重发数据。

    此外,也有可能因为一些其他原因导致确认应答延迟到达,在源主机重发数据以后才到达的情况也屡见不鲜。此时,源主机只要按照机制重发数据即可。

    对于目标主机来说,反复收到相同的数据是不可取的。为了对上层应用提供可靠的传输,目标主机必须放弃重复的数据包。为此我们引入了序列号。

    序列号是按照顺序给发送数据的每一个字节(8位字节)都标上号码的编号。接收端查询接收数据 TCP 首部中的序列号和数据的长度,将自己下一步应该接收的序列号作为确认应答返送回去。通过序列号和确认应答号,TCP 能够识别是否已经接收数据,又能够判断是否需要接收,从而实现可靠传输。

    6.6、TCP中的滑动窗口

    发送方和接收方都会维护一个数据帧的序列,这个序列被称作窗口。发送方的窗口大小由接收方确认,目的是控制发送速度,以免接收方的缓存不够大导致溢出,同时控制流量也可以避免网络拥塞。

    在TCP 的可靠性的图中,我们可以看到,发送方每发送一个数据接收方就要给发送方一个ACK对这个数据进行确认。只有接收了这个确认数据以后发送方才能传输下个数据。

    存在的问题:如果窗口过小,当传输比较大的数据的时候需要不停的对数据进行确认,这个时候就会造成很大的延迟。

    如果窗口过大,我们假设发送方一次发送100个数据,但接收方只能处理50个数据,这样每次都只对这50个数据进行确认。发送方下一次还是发送100个数据,但接受方还是只能处理50个数据。这样就避免了不必要的数据来拥塞我们的链路。

    因此,我们引入了滑动窗口。滑动窗口通俗来讲就是一种流量控制技术。

    它本质上是描述接收方的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算自己最多能发送多长的数据,如果发送方收到接收方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接收方发送窗口大小不为0的数据报的到来。

    首先是第一次发送数据这个时候的窗口大小是根据链路带宽的大小来决定的。我们假设这个时候窗口的大小是3。这个时候接受方收到数据以后会对数据进行确认告诉发送方我下次希望手到的是数据是多少。这里我们看到接收方发送的ACK=3(这是发送方发送序列2的回答确认,下一次接收方期望接收到的是3序列信号)。这个时候发送方收到这个数据以后就知道我第一次发送的3个数据对方只收到了2个。就知道第3个数据对方没有收到。下次在发送的时候就从第3个数据开始发。

    此时窗口大小变成了2 。

    于是发送方发送2个数据。看到接收方发送的ACK是5就表示他下一次希望收到的数据是5,发送方就知道我刚才发送的2个数据对方收了这个时候开始发送第5个数据。

    这就是滑动窗口的工作机制,当链路变好了或者变差了这个窗口还会发生变话,并不是第一次协商好了以后就永远不变了。                

    所以滑动窗口协议,是TCP使用的一种流量控制方法。该协议允许发送方在停止并等待确认前可以连续发送多个分组。由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输。

    只有在接收窗口向前滑动时(与此同时也发送了确认),发送窗口才有可能向前滑动。   

    收发两端的窗口按照以上规律不断地向前滑动,因此这种协议又称为滑动窗口协议。   

    七、UDP协议

    UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。

    UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编程验证。

    UDP与TCP位于同一层,但它不管数据包的顺序、错误或重发。因此,UDP不被应用于那些面向连接的服务,UDP主要用于那些面向查询---应答的服务,例如NFS。相对于FTP或Telnet,这些服务需要交换的信息量较小。使用UDP的服务包括NTP(网络时间协议)和DNS(DNS也使用TCP),包总量较少的通信(DNS、SNMP等);2.视频、音频等多媒体通信(即时通信);3.限定于 LAN 等特定网络中的应用通信;4.广播通信(广播、多播)。

    常用的QQ,就是一个以UDP为主,TCP为辅的通讯协议。

    TCP 和 UDP 的优缺点无法简单地、绝对地去做比较:TCP 用于在传输层有必要实现可靠传输的情况;而在一方面,UDP 主要用于那些对高速传输和实时性有较高要求的通信或广播通信。TCP 和 UDP 应该根据应用的目的按需使用。

    八、HTTP协议介绍

    HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。

    我们使用http来访问Web上某个资源,比如html/文本、word、avi电影、其他资源。

    Content-Type指示响应的内容,这里是text/html表示HTML网页。请注意,浏览器就是依靠Content-Type来判断响应的内容是网页还是图片,是视频还是音乐。浏览器并不靠URL来判断响应的内容,所以,即使URL是http://example.com/abc.jpg,它也不一定就是图片。

    HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息。

    URL,全称是UniformResourceLocator, 中文叫统一资源定位符,是互联网上用来标识某一处资源的地址。

    8.1、URI和URL的区别

    URI是个纯粹的句法结构,用于指定标识Web资源的字符串的各个不同部分。URL是URI的一个特例,它包含了定位Web资源的足够信息。其他URI,比如

    mailto:cay@horstman.com

    则不属于定位符,因为根据该标识符无法定位任何资源。

    URI 是统一资源标识符,而 URL 是统一资源定位符。因此,笼统地说,每个 URL 都是 URI,但不一定每个 URI 都是 URL。这是因为 URI 还包括一个子类,即统一资源名称 (URN),它命名资源但不指定如何定位资源。上面的 mailto就是一个URN 的示例。

    URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。

    8.2、一个完整的URL

    包括以下几部分:

    http://www.enjoyedu.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name

    1.协议部分:该URL的协议部分为“http:”,这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。在"HTTP"后面的“//”为分隔符

    2.域名部分:该URL的域名部分为“www.enjoyedu.com”。一个URL中,也可以使用IP地址作为域名使用

    3.端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口

    4.虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是“/news/”

    5.文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名

    6.锚部分:从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个URL必须的部分

    7.参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。

    8.3、HTTP请求的传输过程

    首先作为发送端的客户端在应用层(HTTP 协议)发出一个想看某个 Web 页面的 HTTP 请求。

    接着,为了传输方便,在传输层(TCP 协议)把从应用层处收到的数据(HTTP 请求报文)进行分割,并在各个报文上打上标记序号及端口号后转发给网络层。

    在网络层(IP 协议),增加作为通信目的地的 MAC 地址后转发给链路层。这样一来,发往网络的通信请求就准备齐全了。

    接收端的服务器在链路层接收到数据,按序往上层发送,一直到应用层。当传输到应用层,才能算真正接收到由客户端发送过来的 HTTP请求。

    一次完整http请求的过程

    首先进行DNS域名解析(本地浏览器缓存、操作系统缓存或者DNS服务器)

    建立 TCP 连接

    在HTTP工作开始之前,客户端首先要通过网络与服务器建立连接,该连接是通过 TCP 来完成的,该协议与 IP 协议共同构建 Internet,即著名的 TCP/IP 协议族,因此 Internet 又被称作是 TCP/IP 网络。HTTP 是比 TCP 更高层次的应用层协议,根据规则,只有低层协议建立之后,才能进行高层协议的连接,因此,首先要建立 TCP 连接,一般 TCP 连接的端口号是80;

    •  客户端向服务器发送请求命令

    一旦建立了TCP连接,客户端就会向服务器发送请求命令;

    例如:GET/sample/hello.jsp HTTP/1.1

    •  客户端发送请求头信息

    客户端发送其请求命令之后,还要以头信息的形式向服务器发送一些别的信息,之后客户端发送了一空白行来通知服务器,它已经结束了该头信息的发送;

    •  服务器应答

    客户端向服务器发出请求后,服务器会客户端返回响应;

    例如: HTTP/1.1 200 OK

    响应的第一部分是协议的版本号和响应状态码

    •  服务器返回响应头信息

    正如客户端会随同请求发送关于自身的信息一样,服务器也会随同响应向用户发送关于它自己的数据及被请求的文档;

    •  服务器向客户端发送数据

    服务器向客户端发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以 Content-Type 响应头信息所描述的格式发送用户所请求的实际数据;

    •  服务器关闭 TCP 连接

    一般情况下,一旦服务器向客户端返回了请求数据,它就要关闭 TCP 连接,然后如果客户端或者服务器在其头信息加入了这行代码 Connection:keep-alive ,TCP 连接在发送后将仍然保持打开状态,于是,客户端可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。

    以下为整个HTTP请求的抓包

    8.4、HTTP 协议报文结构

    用于 HTTP 协议交互的信息被称为 HTTP 报文。请求端(客户端)的 HTTP 报文叫做请求报文;响应端(服务器端)的叫做响应报文。HTTP 报文本身是由多行(用 CR+LF 作换行符)数据构成的字符串文本。

    HTTP 报文大致可分为报文首部和报文主体两部分。两者由最初出现的空行(CR+LF)来划分。通常,并不一定有报文主体。

    请求报文结构

    请求报文的首部内容由以下数据组成:

    请求行 —— 包含用于请求的方法、请求 URI 和 HTTP 版本。

    首部字段 —— 包含表示请求的各种条件和属性的各类首部。(通用首部、请求首部、实体首部以及RFC里未定义的首部如 Cookie 等)

    响应报文结构

    状态行 —— 包含表明响应结果的状态码、原因短语和 HTTP 版本。

    首部字段 —— 包含表示请求的各种条件和属性的各类首部。(通用首部、响应首部、实体首部以及RFC里未定义的首部如 Cookie 等)

     

    展开全文
  • 计算机网络实验二:网络基础编程实验

    万次阅读 多人点赞 2019-04-16 13:49:46
    Socket(套接字)是一种抽象层,应用程序通过它来发送接收数据,就像应用程序打开一个文件句柄,将数据读写到稳定的存储器上一样。一个socket允许应用程序添加到网络中,并与处于同一个网络中的其他应用程序进行...

    一、实验目的

     

    通过本实验,学习采用Socket(套接字)设计简单的网络数据收发程序,理解应用数据包是如何通过传输层进行传送的。

     

    二、实验内容

     

    Socket(套接字)是一种抽象层,应用程序通过它来发送和接收数据,就像应用程序打开一个文件句柄,将数据读写到稳定的存储器上一样。一个socket允许应用程序添加到网络中,并与处于同一个网络中的其他应用程序进行通信。一台计算机上的应用程序向socket写入的信息能够被另一台计算机上的另一个应用程序读取,反之亦然。

    不同类型的socket与不同类型的底层协议族以及同一协议族中的不同协议栈相关联。现在TCP/IP协议族中的主要socket类型为流套接字(sockets sockets)和数据报套接字(datagram sockets)。

    流套接字将TCP作为其端对端协议(底层使用IP协议),提供了一个可信赖的字节流服务。一个TCP/IP流套接字代表了TCP连接的一端。数据报套接字使用UDP协议(底层同样使用IP协议),提供了一个"尽力而为"(best-effort)的数据报服务,应用程序可以通过它发送最长65500字节的个人信息。一个TCP/IP套接字由一个互联网地址,一个端对端协议(TCP或UDP协议)以及一个端口号唯一确定。

    当一个客户端向一个已经被其他客户端占用的服务器发送连接请求时,虽然其在连接建立后即可向服务器端发送数据,服务器端在处理完已有客户端的请求前,却不会对新的客户端作出响应。

    并行服务器:可以单独处理没一个连接,且不会产生干扰。并行服务器分为两种:一客户一线程和线程池。每个新线程都会消耗系统资源:创建一个线程将占用CPU周期,而且每个线程都自己的数据结构(如,栈)也要消耗系统内存。另外,当一个线程阻塞(block)时,JVM将保存其状态,选择另外一个线程运行,并在上下文转换(context switch)时恢复阻塞线程的状态。随着线程数的增加,线程将消耗越来越多的系统资源。这将最终导致系统花费更多的时间来处理上下文转换和线程管理,更少的时间来对连接进行服务。那种情况下,加入一个额外的线程实际上可能增加客户端总服务时间。

    我们可以通过限制总线程数并重复使用线程来避免这个问题。与为每个连接创建一个新的线程不同,服务器在启动时创建一个由固定数量线程组成的线程池(thread pool)。当一个新的客户端连接请求传入服务器,它将交给线程池中的一个线程处理。

    当该线程处理完这个客户端后,又返回线程池,并为下一次请求处理做好准备。如果连接请求到达服务器时,线程池中的所有线程都已经被占用,它们则在一个队列中等待,直到有空闲的线程可用。

     

    三、实验步骤

     

    1、采用TCP进行数据发送的简单程序(java/python3.5)

    2、采用UDP进行数据发送的简单程序(java/python3.5)

    3、多线程\线程池对比(java/python3.5)

    4、写一个简单的chat程序,并能互传文件,编程语言不限。

     

    四、实验过程和结果(使用python3.5)

     

    1、使用TCP进行的数据收发

     

    使用TCP的网络连接,需要用到python中的socket模块,所以首先需要在代码中,将它导入进来:

    import socket

    接下来需要制定TCP通信的端口号,这里的IP地址选为127.0.0.1,即本地服务器local host:

    ip_port = ('127.0.0.1',10000)

    端口号的制定可以随意,只要确保客户端和服务器使用的是同一组端口即可。接下来需要使用socket关键字声明一个新的套接字,用于接下来的通信过程,操作为:sk=socket.socket()

    建立连接的过程比较简单,使用connect函数即可:sk.connect(ip_port),此时,通信连接已经建立完成,下面可以进行数据的收发。

     

    首先,服务器需要通过accept系统调用方法,获取到给它发送数据的客户端的IP地址等信息:

    conn,addr = sk.accept()

    其中,conn为连接的实体,addr为目标的地址。

    从客户端发出给服务器的数据需要将该字符串表示的信息使用encode加码,满足通信的格式和协议。encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode('gb2312'),表示将unicode编码的字符串str2转换成gb2312编码:

    sk.sendall(str('Client:'+message).encode())

    而服务器收到的unicode数据需要通过解码才能以字符串形式显示出来。decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode('gb2312'),表示将gb2312编码的字符串str1转换成unicode编码:

    print(client_data.decode())

    在收发数据的过程中,需要一个缓冲区以接收发送和发出的数据,这样的缓冲区数据通过recv方法读取。每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式以及TCP的流量(拥塞)控制便是依赖于这两个独立的buffer以及buffer的填充状态。接收缓冲区把数据缓存入内核,应用进程一直没有调用recv()进行读取的话,此数据会一直缓存在相应socket的接收缓冲区内。实现为:

    client_data = conn.recv(1024)

    在程序的流程方面,需要加上while true保证客户机和服务器能多次循环收发数据。

     

    完整代码

    【客户端】
    
    import socket
    ip_port = ('127.0.0.1',10000)
    
    while True:
        sk = socket.socket()
        sk.connect(ip_port)
        message=input('Send:')
        sk.sendall(str('Client:'+message).encode())
        print('Client waiting...')
        server_reply = sk.recv(1024)
        print (server_reply.decode())
    
    sk.close()
    【服务器】
    
    import socket
    
    ip_port = ('127.0.0.1',10000)
    
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('Server waiting...')
        conn,addr = sk.accept()
    
        client_data = conn.recv(1024)
        print(client_data.decode()) 
        message=input('Send:')
        
        conn.sendall(str('Server:'+message).encode())
        conn.close()

    2、使用UDP的数据收发

     

    与TCP连接不同,UDP最大的区别在于连接的声明方式不同:

    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    UDP套接字的名字:SOCK_DGRAM(无连接的套接字),特点是不可靠(局网内还是比较可靠的),开销小。

    与虚拟电路形成鲜明对比的是数据报类型的套接字,它是一种无连接的套接字。在通信开始之前并不需要建立连接。此时,在数据传输过程中并无法保证它的顺序性、可靠性或重复性。数据报确实保存了记录边界,这就意味着消息是以整体发送的,而并非首先分成多个片段。实现这种连接类型的主要协议是用户数据报协议(缩写 UDP)。为了创建UDP套接字,必须使用SOCK_DGRAM作为套接字类型。

    其余数据传输内容,与基于TCP的传输一致。

     

    完整代码

    【客户端】
    
    import socket
    
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    while True:
        msg = input("Send:")
        server_address = ("127.0.0.1", 8000)
        client_socket.sendto(msg.encode(), server_address)
        print('Client waiting...')
        receive_data, sender_address = client_socket.recvfrom(1024)
        print("Server:"+str(receive_data.decode()))
    【服务器】
    
    import socket
    
    PORT = 8000
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    address = ("127.0.0.1", PORT)
    server_socket.bind(address)
    while True:
        print('Server waiting...')   
        receive_data, client_address = server_socket.recvfrom(1024)
        print("Client:"+ str(receive_data.decode()))
        msg = input("Send:")
        server_socket.sendto(msg.encode(), client_address)

     

    3、使用多线程的数据传输

     

    多线程与单线程的传输连接的不同点也在于连接的声明方式,即为每一个连接客户端建立一个线程,连接将使用Threading方法,被如下声明:

    server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),MyServer)

    其余流程与操作,与单线程传输无区别。

    值得一提的是,当时验收的时候助教问我是线程池更快还是多线程更快,答案应该是线程池。因为线程池首先建立了很多个线程,当有客户端连接的时候,唤醒即可;而多线程则是来一个建立一个,每一次都要建立,每次用完都要删除。因此线程池是一个更加快速的选择。

    完整代码

    【客户端】
    
    import socket
    
    ip_port = ('127.0.0.1',8009)
    sk = socket.socket()
    sk.connect(ip_port)
    sk.settimeout(5)
    
    while True:
        data = sk.recv(1024)
        print('receive:',data.decode())
        inp = input('please input:')
        sk.sendall(inp.encode())
        if inp == 'exit':
            break
    
    sk.close()
    【服务器】
    
    import socketserver
    
    class MyServer(socketserver.BaseRequestHandler):
    
        def handle(self):
            # print self.request,self.client_address,self.server
            conn = self.request
            conn.sendall('请输入按键选择,0转人工服务.'.encode())
            Flag = True
            while Flag:
                data = conn.recv(1024).decode()
                if data == 'exit':
                    Flag = False
                elif data == '0':
                    conn.sendall('通信可能会被记录...'.encode())
                else:
                    conn.sendall('请重新输入.'.encode())
    
    if __name__ == '__main__':
        server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
        server.serve_forever()

     

    4、文件的传输

     

    文件的传输涉及到操作系统当中的文件系统,即需要为需要传输的文件制定该文件的路径。

    在建立连接的方法上,与之前的TCP连接是一样的。

    不同之处在于文件的发送以及接收处理上。首先,文件的大小是不确定的,而实际传输中往往使用的是缓冲区,如果不能够事先知道文件的大小,会导致传输的数据出错,因此,需要先获取文件名和大小,并为了防止粘包,将这两个信息拼接起来,给客户端发送一个信号:

    Informf=(str(file_name)+'|'+str(file_size)) 客户端的打包
    file_name,file_size = pre_data.split('|') 服务器的解包

    通过语句msg=sk.recv(1024),指定了缓冲区的大小为1024字节,因此需要对于文件循环读取,直到文件的数据填满了一个缓冲区,此时将缓冲区数据发送出去,继续读取下一部分文件;或是当缓冲区未填满,而文件读取完毕,此时应当将这个未满的缓冲区发送给服务器。

    while Flag:
            if send_size + 1024 >file_size:
                data = f.read(file_size-send_size)
                Flag = False
            else:
                data = f.read(1024)
                send_size+=1024
            sk.send(data)

    最后,服务器指定一个路径,将该文件传输到该路径下。

     

    完整代码

    【客户端】
    
    import socket
    import os
    
    ip_port = ('127.0.0.1',9922)
    sk = socket.socket()
    sk.connect(ip_port)
    
    container = {'key':'','data':''}
    while True:
        # 客户端输入要上传文件的路径
        path = input('输入路径名:')
        # 根据路径获取文件名
        file_name = os.path.basename(path)
        #print(file_name)
        # 获取文件大小
        file_size=os.stat(path).st_size
        # 发送文件名 和 文件大小
        Informf=(str(file_name)+'|'+str(file_size))
        sk.send(Informf.encode())
        # 为了防止粘包,将文件名和大小发送过去之后,等待服务端收到,直到从服务端接受一个信号(说明服务端已经收到)
        sk.recv(1024)
        send_size = 0
        f= open(path,'rb')
        Flag = True
        while Flag:
            if send_size + 1024 >file_size:
                data = f.read(file_size-send_size)
                Flag = False
            else:
                data = f.read(1024)
                send_size+=1024
            sk.send(data)
        msg=sk.recv(1024)
        print(msg.decode())
        f.close()
        os.system("start C:\\users\yyd\desktop\Send")
        
    sk.close()
    【服务器】
    
    import socketserver
    import os
    
    class MyServer(socketserver.BaseRequestHandler):
        def handle(self):
            base_path = 'C:\\users\yyd\desktop\Send'
            conn = self.request
            print ('Connected to client')
            print ('Upload waiting...')
            while True:
                pre_data = conn.recv(1024).decode()
                #获取请求方法、文件名、文件大小
                file_name,file_size = pre_data.split('|')
                # 防止粘包,给客户端发送一个信号。
                conn.sendall('nothing'.encode())
                #已经接收文件的大小
                recv_size = 0
                #上传文件路径拼接
                file_dir = os.path.join(base_path,file_name)
                f = open(file_dir,'wb')
                Flag = True
                while Flag:
                    #未上传完毕,
                    if int(file_size)>recv_size:
                        #最多接收1024,可能接收的小于1024
                        data = conn.recv(1024)
                        recv_size+=len(data)
                        #写入文件
                        f.write(data)
                    #上传完毕,则退出循环
                    else:
                        recv_size = 0
                        Flag = False
                
                msg="Upload successed."
                print(msg)
                conn.sendall(msg.encode())
                
                f.close()
        
    instance = socketserver.ThreadingTCPServer(('127.0.0.1',9922),MyServer)
    instance.serve_forever()

     

    展开全文
  • Java 计算机网络网络编程总结)

    千次阅读 2018-10-05 20:31:52
    计算机网络是通过传输介质、通信设施网络通信协议,把分散在不同地点的计算机设备互连起来,实现资源共享数据传输的系统。网络编程就就是编写程序使联网的两个(或多个)设备(例如计算机)之间进行数据传输。...

    本文主要是自己在网络编程方面的学习总结,先主要介绍计算机网络方面的相关内容,包括计算机网络基础,OSI参考模型,TCP/IP协议簇,常见的网络协议等等,在此基础上,介绍Java中的网络编程。

    一、概述

    计算机网络是通过传输介质、通信设施和网络通信协议,把分散在不同地点的计算机设备互连起来,实现资源共享和数据传输的系统。网络编程就就是编写程序使联网的两个(或多个)设备(例如计算机)之间进行数据传输。Java语言对网络编程提供了良好的支持,通过其提供的接口我们可以很方便地进行网络编程。下面先对网络编程的一些基础知识进行介绍,最后给出使用Java语言进行网络编程的实例。

    二、计算机网络

    计算机网络20世纪60年代出现,经历了20世纪70年代、80年代和90年代的发展,进入21世纪后,计算机网络已经成为信息社会的基础设施,深入到人类社会的方方面面,与人们的工作、学习和生活息息相关。

    网络协议

    如同人与人之间相互交流是需要遵循一定的规矩一样,计算机之间能够进行相互通信是因为它们都共同遵守一定的规则,即网络协议。

    网络体系结构

    计算机网络是个复杂的系统,按照人们解决复杂问题的方法,把计算机网络实现的功能分到不同的层次上,层与层之间用接口连接。通信的双方具有相同的层次,层次实现的功能由协议数据单元(PDU)来描述。不同系统中的同一层构成对等层,对等层之间通过对等层协议进行通信,理解彼此定义好的规则和约定。

    计算机网络体系结构是计算机网络层次和协议的集合,网络体系结构对计算机网络实现的功能,以及网络协议、层次、接口和服务进行了描述,但并不涉及具体的实现。接口是同一节点内相邻层之间交换信息的连接处,也叫服务访问点(SAP)。

    计算机网络层次模型

    三、OSI参考模型

    前面我们介绍了计算机网络的体系结构,因为计算机网络是个复杂的系统,所以把计算机网络实现的功能分到不同的层次上,而计算机网络体系结构是计算机网络层次和协议的集合。那么,计算机网络如何进行分层呢?下面先介绍的是OSI参考模型。

    简介

    世界上第一个网络体系结构由IBM公司提出(1974年,SNA),以后其他公司也相继提出自己的网络体系结构如:Digital公司的DNA,美国国防部的TCP/IP等,多种网络体系结构并存,其结果是若采用IBM的结构,只能选用IBM的产品,只能与同种结构的网络互联。

    为了促进计算机网络的发展,国际标准化组织ISO于1977年成立了一个委员会,在现有网络的基础上,提出了不基于具体机型、操作系统或公司的网络体系结构,称为开放系统互连参考模型,即OSI/RM (Open System Interconnection Reference Model)。OSI模型把网络通信的工作分为7层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。

    OSI参考模型的7个层次

    OSI模型层次功能

    • 物理层

    物理层处于OSI的最底层,是整个开放系统的基础。物理层涉及通信信道上传输的原始比特流(bits),它的功能主要是为数据端设备提供传送数据的通路以及传输数据。

    • 数据链路层

    数据链路层的主要任务是实现计算机网络中相邻节点之间的可靠传输,把原始的、有差错的物理传输线路加上数据链路协议以后,构成逻辑上可靠的数据链路。需要完成的功能有链路管理、成帧、差错控制以及流量控制等。其中成帧是对物理层的原始比特流进行界定,数据链路层也能够对帧的丢失进行处理。

    • 网络层

    网络层涉及源主机节点到目的主机节点之间可靠的网络传输,它需要完成的功能主要包括路由选择、网络寻址、流量控制、拥塞控制、网络互连等。

    • 传输层

    传输层起着承上启下的作用,涉及源端节点到目的端节点之间可靠的信息传输。传输层需要解决跨越网络连接的建立和释放,对底层不可靠的网络,建立连接时需要三次握手,释放连接时需要四次挥手。

    • 会话层和表示层

    会话层的主要功能是负责应用程序之间建立、维持和中断会话,同时也提供对设备和结点之间的会话控制,协调系统和服务之间的交流,并通过提供单工、半双工和全双工3种不同的通信方式,使系统和服务之间有序地进行通信。

    表示层关心所传输数据信息的格式定义,其主要功能是把应用层提供的信息变换为能够共同理解的形式,提供字符代码、数据格式、控制信息格式、加密等的统一表示。

    • 应用层

    应用层为OSI的最高层,是直接为应用进程提供服务的。其作用是在实现多个系统应用进程相互通信的同时,完成一系列业务处理所需的服务。

    四、TCP/IP参考模型

    OSI参考模型的初衷是提供全世界范围的计算机网络都要遵循的统一标准,但是由于存在模型和协议自身的缺陷,迟迟没有成熟的产品推出。TCP/IP协议在实践中不断完善和发展取得成功,作为网络的基础,Internet的语言,可以说没有TCP/IP协议就没有互联网的今天。

    简介

    TCP/IP,即Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,是Internet最基本的协议、Internet国际互联网络的基础。

    TCP/IP协议是一个开放的网络协议簇,它的名字主要取自最重要的网络层IP协议和传输层TCP协议。TCP/IP协议定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。TCP/IP参考模型采用4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求,这4个层次分别是:网络接口层、互联网层(IP层)、传输层(TCP层)、应用层。

    OSI 和 TCP/IP模型对比

    TCP/IP模型层次功能

    • 网络接口层

    TCP/IP协议对网络接口层没有给出具体的描述,网络接口层对应着物理层和数据链路层。

    • 互联网层 ( IP层 )

    互联网层是整个TCP/IP协议栈的核心。它的功能是把分组发往目标网络或主机。同时,为了尽快地发送分组,可能需要沿不同的路径同时进行分组传递。因此,分组到达的顺序和发送的顺序可能不同,这就需要上层必须对分组进行排序。互联网层除了需要完成路由的功能外,也可以完成将不同类型的网络(异构网)互连的任务。除此之外,互联网层还需要完成拥塞控制的功能。

    • 传输层 ( TCP层 )

    TCP层负责在应用进程之间建立端到端的连接和可靠通信,它只存在与端节点中。TCP层涉及两个协议,TCP和UDP。其中,TCP协议提供面向连接的服务,提供按字节流的有序、可靠传输,可以实现连接管理、差错控制、流量控制、拥塞控制等。UDP协议提供无连接的服务,用于不需要或无法实现面向连接的网络应用中。

    • 应用层

    应用层为Internet中的各种网络应用提供服务。

    五、常见网络协议

    上面主要介绍了OSI参考模型和TCP/IP模型的相关内容,从下面这张图可以看出TCP/IP协议簇中不同的层次中有着很多不同的网络协议,下面主要介绍传输层的TCP、UDP协议和应用层的HTTP协议。

    TCP协议

    简介

    TCP(Transmission Control Protocol ,传输控制协议)是面向连接的传输层协议。TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。TCP协议采用字节流传输数据。

    TCP报文段格式

    TCP报文段包括协议首部和数据两部分,协议首部的固定部分有20个字节,首部的固定部分后面是选项部分。

    TCP报文段

    报文段首部各个字段的含义

    • 源端口号以及目的端口号,各占2个字节,端口是传输层和应用层的服务接口,用于寻找发送端和接收端的进程,一般来讲,通过端口号和IP地址,可以唯一确定一个TCP连接,在网络编程中,通常被称为一个socket接口。
    • 序号,占4字节,用来标识从TCP发送端向TCP接收端发送的数据字节流。
    • 确认序号,占4字节,包含发送确认的一端所期望收到的下一个序号,因此,确认序号应该是上次已经成功收到数据字节序号加1.
    • 数据偏移,占4位,用于指出TCP首部长度,若不存在选项,则这个值为20字节,数据偏移的最大值为60字节。
      保留字段占6位,暂时可忽略,值全为0
    • 标志位
      URG(紧急) : 为1时表明紧急指针字段有效
      ACK(确认):为1时表明确认号字段有效
      PSH(推送):为1时接收方应尽快将这个报文段交给应用层
      RST(复位):为1时表明TCP连接出现故障必须重建连接
      SYN(同步):在连接建立时用来同步序号
      FIN (终止): 为1时表明发送端数据发送完毕要求释放连接
    • 接收窗口占2个字节,用于流量控制和拥塞控制,表示当前接收缓冲区的大小。在计算机网络中,通常是用接收方的接收能力的大小来控制发送方的数据发送量。TCP连接的一端根据缓冲区大小确定自己的接收窗口值,告诉对方,使对方可以确定发送数据的字节数。
    • 校验和占2个字节,范围包括首部和数据两部分。
    • 选项是可选的,默认情况是不选。

    三次握手与四次挥手

    TCP是面向连接的协议,因此每个TCP连接都有3个阶段:连接建立、数据传送和连接释放。连接建立经历三个步骤,通常称为“三次握手”。

    TCP三次握手过程如下:

    TCP三次握手

    第一次握手

    客户机发送连接请求报文段到服务器,并进入SYN_SENT状态,等待服务器确认。(SYN = 1,seq=x)

    第二次握手

    服务器收到连接请求报文,如果同意建立连接,向客户机发回确认报文段,并为该TCP连接分配TCP缓存和变量。(SYN=1,ACK=1,seq=y,ack=x+1)。

    第三次握手

    客户机收到服务器的确认报文段后,向服务器给出确认报文段,并且也要给该连接分配缓存和变量。此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。(ACK=1,seq=x+1,ack=y+1)。

    TCP四次挥手过程如下:

    四次挥手

    由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

    1. TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
    2. 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
    3. 服务器关闭客户端的连接,发送一个FIN给客户端。
    4. 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

    UDP协议

    • 简介

    UDP,用户数据报协议,英文全称是User Datagram Protocol,它是TCP/IP协议簇中无连接的运输层协议。

    • UDP协议格式

    UDP格式

    从图中可以看到,UDP协议十分简单,它由两部分组成:首部和数据。其中,首部仅有8个字节,包括源端口和目的端口,长度(UDP用于数据报的长度)、校验和。

    HTTP协议

    • 简介

    HTTP,超文本传输协议,英文全称是Hypertext Transfer Protocol,它是互联网上应用最为广泛的一种网络协议。HTTP是一种应用层协议,它是基于TCP协议之上的请求/响应式的协议,即一个客户端与服务器建立连接后,向服务器发送一个请求;服务器接到请求后,给予相应的响应信息。HTTP协议默认的端口号为80.

    现在使用的HTTP协议是HTTP/1.1版本,1997年之前采用的是HTTP1.0版本。HTTP连接在1.0版本中采用非持续连接工作方式,1.1版本采用的是持续连接工作方式,持续连接是指服务器在发送响应后仍然在一段时间内保持这条由TCP运输层协议建立起来的连接,使客户机和服务器可以继续在这条连接上传输HTTP报文。

    是否采用持续连接工作方式,1.0中默认是关闭的,需要在HTTP头加入"Connection:Keep-Alive",才能启用Keep-Alive。HTTP1.1中默认启用Keep-Alive,如果加入"Connection:close",才关闭。目前大部分浏览器都是用HTTP1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep- Alive连接就看服务器设置情况。

    • HTTP报文

    HTTP协议是基于TCP协议之上的请求/响应式协议,下面主要介绍HTTP报文的格式,HTTP报文主要有请求报文和响应报文两种。首先看请求报文的格式:

    • HTTP请求报文格式

    HTTP请求报文由请求行、首部行和实体主体组成,由浏览器发送给服务器。上面这张图中SP表示空格,cr lf表示回车和换行。

    • HTTP响应报文格式

    上面这张图是HTTP响应报文,它由状态行、首部行和实体主体组成。下面两张图是在谷歌浏览器内访问服务器查看的HTTP请求和响应。

    HTTP请求报文例子

    HTTP响应报文例子

    • HTTP请求方法和响应状态码

    在上面的HTTP请求报文例子中,我们可以看到请求方法是GET,这表示请求读取由URL所标志的信息,除了GET,还有其它几种常用的方法。

    • HTTP请求报文的一些方法

    在HTTP响应报文的例子中,我们可以看到状态码是200,表示响应成功。下表是其它状态码,总共5大类,33种。

    HTTP响应报文的状态码

    HTTPS和HTTP的区别

    HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。

    超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息。HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此HTTP协议不适合传输一些敏感信息,比如信用卡号、密码等。

    为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS。为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。

    HTTPS和HTTP的区别主要为以下四点:1、https协议需要到ca申请证书,一般免费证书很少,需要交费。2、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

    六、常见问题

    到这里,关于计算机网络部分的总结内容就结束了,下面是几个常见的问题,汇总在这里。

    • OSI参考模型的分为哪几层,每层的功能?
      OSI,开放系统互连参考模型,它的7个层次自顶到下依次为应用层,表示层,会话层,传输层,网络层,数据链路层和物理层。各层的功能见文章开始。

    • TCP协议和UDP协议的区别?
      TCP协议是传输控制协议,UDP协议是用户数据报协议,两者都是传输层的协议,主要区别在于前者是可靠的,面向连接的协议,后者是不可靠的,无连接的协议。其它的区别还有,TCP协议传输速度慢,UDP常用于一次性传输比较少量数据的网络应用。

    • TCP三次握手为什么不能是两次?
      主要是防止两次握手情况下已经失效的连接请求报文段突然又传送到服务端而产生错误。例如,客户机A向服务器B发送TCP连接请求,第一个连接请求报文在网络的某个节点长时间滞留,A超时后认为报文丢失,于是再重传一次连接请求,B收到后建立连接。数据传输完毕后双方断开连接,而这时之前滞留的连接请求到达了服务端B,而B认为A又发来连接请求。如果两次握手建立连接,A并无连接请求,造成B的资源浪费。

    • HTTP请求的GET方法和POST方法的区别?
      GET和POST是HTTP请求的两种方法,主要区别在于GET方法是请求读取由URL所标志的信息,POST是给服务器添加信息。点击查看更多

    • 在浏览器中输入网址到显示出页面的整个过程?
      (1) 输出包含域名的网址
      (2) 浏览器向DNS请求解析域名对应的IP地址
      (3) 域名系统DNS解析出域名对应的IP地址
      (4) 浏览器与该服务器建立TCP连接
      (5) 浏览器发送HTTP请求
      (6) 服务器通过HTTP响应把页面文件发送给浏览器
      (7) TCP连接释放
      (8) 浏览器解释文件,并显示

    七、Java网络编程

    Java的网络编程主要涉及到的内容是Socket编程,那么什么是Socket呢?简单地说,Socket,套接字,就是两台主机之间逻辑连接的端点。TPC/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据。Socket,本质上就是一组接口,是对TCP/IP协议的封装和应用(程序员层面上)。

    整体流程

    Socket编程主要涉及到客户端和服务器端两个方面,首先是在服务器端创建一个服务器套接字(ServerSocket),并把它附加到一个端口上,服务器从这个端口监听连接。端口号的范围是0到65536,但是0到1024是为特权服务保留的端口号,我们可以选择任意一个当前没有被其他进程使用的端口。

    客户端请求与服务器进行连接的时候,根据服务器的域名或者IP地址,加上端口号,打开一个套接字。当服务器接受连接后,服务器和客户端之间的通信就像输入输出流一样进行操作。

    • 实例一

    下面是一个客户端和服务器端进行数据交互的简单例子,客户端输入正方形的边长,服务器端接收到后计算面积并返回给客户端,通过这个例子可以初步对Socket编程有个把握。

    服务器端

    public class SocketServer {
    
        public static void main(String[] args) throws IOException {
    
            // 端口号
            int port = 7000;
            // 在端口上创建一个服务器套接字
            ServerSocket serverSocket = new ServerSocket(port);
            // 监听来自客户端的连接
            Socket socket = serverSocket.accept();
    
            DataInputStream dis = new DataInputStream(
                    new BufferedInputStream(socket.getInputStream()));
    
            DataOutputStream dos = new DataOutputStream(
                    new BufferedOutputStream(socket.getOutputStream()));
    
            do {
    
                double length = dis.readDouble();
                System.out.println("服务器端收到的边长数据为:" + length);
                double result = length * length;
                dos.writeDouble(result);
                dos.flush();
    
            } while (dis.readInt() != 0);
    
            socket.close();
            serverSocket.close();
        }
    }
    

    客户端

    public class SocketClient {
    
        public static void main(String[] args) throws UnknownHostException, IOException {
    
            int port = 7000;
    
            String host = "localhost";
    
            // 创建一个套接字并将其连接到指定端口号
            Socket socket = new Socket(host, port);
    
            DataInputStream dis = new DataInputStream(
                    new BufferedInputStream(socket.getInputStream()));
    
            DataOutputStream dos = new DataOutputStream(
                    new BufferedOutputStream(socket.getOutputStream()));
    
            Scanner sc = new Scanner(System.in);
    
            boolean flag = false;
    
            while (!flag) {
    
                System.out.println("请输入正方形的边长:");
                double length = sc.nextDouble();
    
                dos.writeDouble(length);
                dos.flush();
    
                double area = dis.readDouble();
    
                System.out.println("服务器返回的计算面积为:" + area);
    
                while (true) {
    
                    System.out.println("继续计算?(Y/N)");
    
                    String str = sc.next();
    
                    if (str.equalsIgnoreCase("N")) {
                        dos.writeInt(0);
                        dos.flush();
                        flag = true;
                        break;
                    } else if (str.equalsIgnoreCase("Y")) {
                        dos.writeInt(1);
                        dos.flush();
                        break;
                    }
                }
            }
    
            socket.close();
        }
    }
    
    • 实例二

    可以看到上面的服务器端程序和客户端程序是一对一的关系,为了能让一个服务器端程序能同时为多个客户提供服务,可以使用多线程机制,每个客户端的请求都由一个独立的线程进行处理。下面是改写后的服务器端程序。

    public class SocketServerM {
    
        public static void main(String[] args) throws IOException {
    
            int port = 7000;
            int clientNo = 1;
    
            ServerSocket serverSocket = new ServerSocket(port);
    
            // 创建线程池
            ExecutorService exec = Executors.newCachedThreadPool();
    
            try {
    
                while (true) {
                    Socket socket = serverSocket.accept();
                    exec.execute(new SingleServer(socket, clientNo));
                    clientNo++;
                }
    
            } finally {
                serverSocket.close();
            }
    
        }
    }
    
    class SingleServer implements Runnable {
    
        private Socket socket;
        private int clientNo;
    
        public SingleServer(Socket socket, int clientNo) {
            this.socket = socket;
            this.clientNo = clientNo;
        }
    
        @Override
        public void run() {
    
            try {
    
                DataInputStream dis = new DataInputStream(
                        new BufferedInputStream(socket.getInputStream()));
    
                DataOutputStream dos = new DataOutputStream(
                        new BufferedOutputStream(socket.getOutputStream()));
    
                do {
    
                    double length = dis.readDouble();
                    System.out.println("从客户端" + clientNo + "接收到的边长数据为:" + length);
                    double result = length * length;
                    dos.writeDouble(result);
                    dos.flush();
    
                } while (dis.readInt() != 0);
    
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                System.out.println("与客户端" + clientNo + "通信结束");
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    上面改进后的服务器端代码可以支持不断地并发响应网络中的客户请求。关键的地方在于多线程机制的运用,同时利用线程池可以改善服务器程序的性能。

    展开全文
  • 计算机网络编程(转载)

    千次阅读 2018-04-18 15:27:57
    1.网络编程  1.1计算机网络概述  网络编程的实质就是两个(或多个)设备(例如计算机)之间的数据传输。  按照计算机网络的定义,通过一定的物理设备将处于不同位置的计算机连接起来组成的网络,这个网络中包含的...
  • 计算机网络自顶向下方法套接字编程作业

    千次阅读 多人点赞 2018-11-30 22:34:02
    本博客是针对,《计算机网络自顶向下方法》一书第二章后面套接字编程作业, 所有代码均已上传至我的github:https://github.com/inspurer/ComputerNetwork 所有代码均本人亲自编写,有问题欢迎评论交流; 如需转载请...
  • 计算机网络高级软件编程技术第5章 IP包流量分析程序源代码
  • 计算机网络高级软件编程技术第10章 滑动窗口协议模拟程序源代码
  • 计算机网络实验——基于TCP协议的socket编程

    万次阅读 多人点赞 2018-06-15 16:44:03
    2. 熟悉c++、Java等高级编程语言网络编程的基本操作。3. 基本了解对话框应用程序的编写过程。4. 实现TCP套接字编程。 二、实验内容(一)实验思路1、学习理解TCP协议。2、实现TCP客户端之间多线程通信以及聊天...
  • 计算机网络高级软件编程技术(第二版)
  • 计算机网络笔记整理

    千次阅读 多人点赞 2018-05-24 16:18:42
    阅读目录1. 网络层次划分2. OSI七层网络模型3. IP地址4. 子网掩码及网络划分5. ARP/RARP协议6....网络协议是为计算机网络中进行数据交换而建立的规则、标准或者说是约定的集合。因为不同用户的数...
  • 计算机网络实验 本程序主要实现两方面功能: 1 聊天:两方可互相发送文本消息 并显示在界面上 2 发送文件:一方请求发送文件 对方可拒绝 也可接收 如果拒绝 则不传输文件 如果接收 则将所选择的文件发送给对方 ">...
  • 计算机网络高级软件编程技术—电子版~ 计算机网络高级软件编程技术—电子版~
  • 编程作业答案 #改为Python3格式 #import socket module from socket import * serverSocket = socket(AF_INET, SOCK_STREAM) #Prepare a sever socket serverPort = 80 serverSocket.bind(("", serv.
  • 计算机网络高级软件编程技术电子书 需用超星阅览器打开
  • Java 网络编程

    万次阅读 多人点赞 2019-05-30 23:07:18
    网络编程 一、网络编程基础概念 首先理清一个概念:网络编程不等于网站编程,网络编程即使用套接字来达到进程间通信,现在一般称为TCP/IP编程。 计算机网络: 把分布在不同地理区域的计算机与专门的外部设备用通信...
  • 本光盘为《计算机网络高级软件编程技术》的配书光盘,内容包括书中所有编程训练的参考答案与完成编程所需要的背景知识、工具与参考资料。 本光盘程序包括代码可执行文件,部分程序不提供完整代码。
  • 老曹眼中的网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为我们拥有网络。网络是一个神奇的东西,它改变了你和我的生活方式,改变了整个世界。 然而,网络的无标度...
  • 编程作业的题目描述: 在本实验中,您将了解Web代理服务器的工作原理及其基本功能之一 —— 缓存。 您的任务是开发一个能够缓存网页的小型Web代理服务器。这是一个很简单的代理服务器,它只能理解简单的GET请求,...
  • ftp客户端(计算机网络编程)ftp客户端(计算机网络编程)ftp客户端(计算机网络编程)ftp客户端(计算机网络编程)ftp客户端(计算机网络编程
  • 编程作业的题目描述: 在这个编程作业中,你将用Python语言开发一个简单的Web服务器,它仅能处理一个请求。具体而言,你的Web服务器将: 当一个客户(浏览器)联系时创建一个连接套接字; 从这个连接套接字接收...
  • 计算机网络高级软件编程技术

    千次阅读 2016-02-13 21:53:13
    本书是在 2008年版的基础上修订的。全书共分23章,第1章为奉书的内容介绍与教学辅导,第2...以实现“通过实际网络编程课题的训练,达到深入理解网络基本工作原理,掌握网络环境中软件编程方法,提高网络软件编程能力
  • 其实有现成的代码改一下就可以了,非要自己写,弄出了...UDP通信需要几个关键对象:DatagramSocket,DatagramPacket,在UDP通信中,传送的数据格式是数据报,在这里就是Datagram,Socket是一个门,在编程者的角度来...
  • 通过网络相关程序的编写,深入理解TCP/IP协议机制,以及初步掌握基于Winsocket的网络编程技术。熟悉原始套接字的编程,了解网络的结构网络传输底层协议。了解IP工作原理,ICMP基于ICMP差错报告报文ICMP询问...
  • 数据结构,计算机网络,数据库,计算机组成原理,操作系统这些在大学期间一定要掌握好来,因为现在互联网大厂面试都爱考察这些内容,一句话,计算机基础,yyds! 可能大家第一个问题是,这些课需要哪些先学? 讲真,...
  • 你不会真的以为自己懂得计算机网络吧?

    千次阅读 多人点赞 2020-02-26 12:17:30
    原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处作者。 思维导图 简介 ...于是,等我读研的时候,打算以相同的学习方式来补一下其他几门计算机基础课程,首当其冲的就是计算机网络。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 341,071
精华内容 136,428
关键字:

计算机网络和网络编程