计算机网络


计算机网络(持续更新)

1.请你来说一下 socket编程中服务器端和客户端主要用到哪些函数

1)基于TCP的socket
1.服务器端程序
1.创建一个socket,用函数socket()
2.绑定IP地址,端口等信息到socket上,用函数bind()
3.开始监听,设定最大连接数用函数listen()
4.接收客户端上的连接,用函数accept()
5.收发数据,用函数send()和recv(),或者read()和write()
6.关闭网络连接

2.客户端程序
1.创建socket(),用函数socket()
2.设置要连接的对方的IP地址和端口等属性
3.连接服务器,用函数connect()
4.收发数据,用send()和recv().或者read(),write()
5.关闭网络连接

2)基于UDP的socket:
1.服务器端流程
1.建立套接字文件描述符,使用函数socket(),生成套接字文件描述符
2.设置服务器地址和侦听端口,初始化要绑定网络地址结构
3.绑定侦听端口,使用bind()函数,将套接字文件描述符和一个地址类型变量进行绑定。
4.接收客户端的数据,使用recvfrom()函数接受客户端的网络数据
5.向客户端发送数据,使用sendto()函数向服务器主机发送数据
6.关闭套接字,使用close()函数释放资源。

2.客户端流程
1.建立套接字文件描述符socket()
2.设置服务器地址和端口,struct sockaddr.
3.向服务器发送数据,sendto()
4.接收服务器数据,recvfrom()
5.关闭套接字,close()

2.TCP拥塞机制

主要是下面四种机制
1.慢开始
慢开始指的是TCP开始发送设置拥塞窗口cwnd= 1.不要一开始就发送大量数据,先探测一下网络的拥塞程度,经过一个轮次的传输,拥塞窗口cwnd加倍。当cwnd超过慢开始门限,则使用拥塞避免算法,防止cwnd增长过大。
2.拥塞避免
每经过一个RTT时间,cwnd就增长1
在慢开始和拥塞避免的过程中一旦发现网络拥塞,就把慢开始门限设置为当前cwnd的一半重新设置cwnd为1.
3.快重传
接收方每次接收到一个失序的报文段之后就应该立即发出重复确认,发送方只要连续收到三次重复确认就立即重传。
4.快速回复
当发送方收到三个连续的重复确认时,就进行乘法减小算法,把慢开始门限设置为当前cwnd的一半,将cwnd设置为慢开始门限大小,执行拥塞避免算法。

3.流量控制服务和拥塞控制服务的区别

TCP接收正确,按序到达的字节后,直接放入接收缓存。相关进程会从当前缓,存读取数据,但是不一定是立即读取,接收方应用或许在忙其他业务,如果发送方读取数据缓慢,就会很容易使该连接接收缓存溢出。
流量控制服务:消除发送方使接收方缓存溢出的可能性。流量控制因此是一个速度匹配的服务。即发送方的发送速率和接收方应用程序的读取速率相匹配。
让发送方维护一个称为接收窗口(rwnd receive window)的变量来提供流量控制。接收窗口用于给发送方一个提示————该接收方窗口还有多少可用的空间。发送方控制发送出去的字节数小于接收窗口的大小。
小问题:发送方维护的rwnd为0.接收方清空缓存,但是并不向发送方发送带有新值的rwnd段。解决当主机B的接收窗口为0的时候,主机A继续发送只有一个字节的数据报段,这样B就可以返回非零的rwnd的值。
拥塞控制:TCP发送方有可能因为IP网络的拥塞而被抑制,这种形式的发送方控制叫做拥塞控制。

4.简述一下TCP的三次握手 四次挥手

握手
1.客户端将报文段首部SYN标志位设置为1,随机生成序号seq=x ,发送给服务器,客户端进入client-sent状态。
2.服务器接收包含SYN=1的数据报,知道了客户端要建立请求连接,客户端将标志位SYN和ACK都设置为1,将确认号置为x+1,随机生成一个序号seq=y,将数据报发回客户端确认连接请求,服务器进入SYN_received状态。
3.客户端收到数据报检查接收的确认号是否为X+1ACK是否为1.如果正确将确认号设置为Y+1发送给服务器,服务器检查确认号是否为Y+1,ack是否为1,如果是则建立连接成功,客户端和服务器进入established状态,可以互相发送数据。

挥手
TCP是全双工连接的,每一方都需要单独关闭,原则是发送FIN来终止任务,首先一方执行主动关闭,另一方执行被动关闭。

1.数据传输结束后,客户端应用进程发出连接解除报文段,并停止发送数据,客户端进入FIN_wait状态,此时客户端依然可以接收数据。
2.服务器接收FIN之后,再发送一个ACK给客户端,确认号为收到序号+1,服务器进入close_wait状态,客户端进入FIN_wait2状态。
3.当服务器端没有数据要发送时,服务器向客户端发送一个FIN报文,此时服务器进入LAST_ACK状态。
4.客户端接收到服务器的FIN报文之后,给服务器发送一个ACK报文,确认序列号是收到序列号+1.此时客户端进入TIME_wait状态,等待一段时间后(报文最大生存时间)关闭连接。

为什么三次握手
为了实现可靠数据传输。TCP协议的通信双方,都必须维护一个序列号,以标识发送出去的数据报中,哪些是已经被对方收到的。三次握手的过程即是通信双方相互告知序列号起始值,并确认对方已经收到序列号起始值的必经步骤。
如果只是两次握手,至多只有连接发起方的起始序列号可以被确认,另一方选择的序列号得不到确认。
防止本来应该失效的连接请求报文又突然回到服务器端造成的浪费。
例如:客户端发送一个SYN,由于网络堵塞,服务器并没有收到这个数据包。然后客户端又重新传了这个SYN数据报并且正确建立TCP连接了,传送完数据,又关闭了TCP连接,这个时候之前发送的SYN数据报来到服务器,服务器发出应答报文段。如果没有采用三次握手连接,此时服务器发送应答报文段表示已经建立起连接,一直等着发送数据。因为客户端没有发起新的请求,会丢弃服务器的SYN。此时服务器会一直等待客户端发送数据而造成资源的浪费。
SYN洪泛攻击。

为什么是四次挥手
为了能够保证数据完成传输,当关闭连接时,当收到FIN报文通知的时候,它仅仅表示对方没有数据发送给你了,但是你的数据未必全部发送给了对方,所以你可以不立刻关闭socket,你还可以继续传输数据给对方。你发送FIN给对方表示你同意关闭连接了,所以这里的FIN和ACk都是分开发送的。

5.IP报文的格式和各个字段的含义

版本号:IPV4就是4.IPV6就是6 (4)
首部长度:IPV4可以包含一些可变参数选项,所以需要一个参数指示数据部分从哪里开始 。一般IPV4数据报具有20字节的首部。(4)
服务类型:不常用 (8)
数据报长度,这个IP数据报的总长度,最多可以传送65535字节的IP数据报。一般不超过1500字节。(16)

标识(16) 标志(3) 片偏移(13):这三个字段与所谓的IP分片有关。

生存时间TTL : 经过一个路由器-1.字段为0时,数据报被丢弃,并且发送ICMP报文通知源主机。(8)
协议 :区分上层协议(8)
首部校验和:将首部字段和反码存入该字段(16)

源和目的IP地址(64)

选项:平常用不到

6.介绍一下IP分片

IP之所以分片是因为不是所有链路层都能承载相同长度的网络分组。例如,以太网能承载不超过1500字节的数据,而某些广域网链路只能承载不超过576字节的数据。一个链路能承载的最大数据量叫做最大传输单元MTU,每种链路可能采用不同的链路层协议,每种协议可能有不同的MTU。

假如在传输过程中,收到的IP数据报字节数比我要转发出去的那条链路的MTU还要大,这个时候就需要将IP进行分解,逐个传输。

标识:数据报被拆分成片后具有相同的标识
标志:最后一个片的标志为0,其他都为1.
偏移:偏移指示该片应该放到初始IP分组的哪个位置,8字节为单位。

7.子网掩码

子网掩码是一种用来指示一个IP地址所标示的主机处于哪个子网当中,子网掩码不能单独存在,他还必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络部分和主机部分。使得路由更方便,先到达子网,再确认是哪个主机。

8.子网掩码类型

因特网地址分配策略为无类别区间路由选择(CIDR)。32比特的IP地址划分成两部分。并且也具有点十分制格式a.b.c.d/x 。x–最高比特构成IP地址的网络部分,在外部路由仅仅需要考虑前x个比特。

具有8,16,24比特子网地址的子网 称为A,B,C类地址,能容纳2^24个地址。B类可容纳65534台主机,C类可容纳254台主机。

9.IP首部校验和是怎么计算的

与ICMP,IGMP,TCP,UDP的首部校验和有什么区别和共同点。

1.先把校验和字段置为0
2.对首部中每个16位比特进行二进制反码求和
3.结果存在校验和字段中
4.收到一份IP数据报后,同样对首部中每个16bit二进制反码求和
5.最后结果全为1 表示正确,否则表示错误
6.如果是错误的,IP就丢弃该数据报,但是不生成差错报文,由上层去处理。

共同点:用到的计算方法都是一样的
区别:IP计算的时候没有将数据包括在内
ICMP,IGMP,TCP,UDP同时覆盖首部和数据校验码

10.I/O多路复用

I/O多路复用使得程序可以同时监听多个文件描述符,能够提高程序的性能。
I/O多路复用出现的场景,是设计一个高性能的网络服务器,能够供多个客户端同时连接并处理客户端传上来的请求。首先想到的是可以利用多线程,但是多线程存在很大的弊端
,需要上下文切换。

select
主旨思想:
1.首先要构造一个关于文件描述符的列表,将要监听的文件描述符添加到该列表中。
2.调用一个系统函数,监听该列表中的文件描述符,直到这些描述符中的一个或者多个进行I/O操作的时候,该函数才返回。
a.这个函数是阻塞的
b.函数对文件描述符的检测操作是由内核完成的
3.在返回的时候,他会告诉进程有哪些文件描述符要进行IO操作

#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
int select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *ecxeptfds,struct timeval *timeout);
    参数:
        -nfds 委托内核检测的最大文件描述符的值+1
        -readfds:要检测的文件描述符的读的集合,委托内核检测哪些文件描述符的读的属性
            -一般检测读操作
            -对应的是对方发送过来的数据,因为读是被动的接收数据,检测的是读缓冲区
            -是一个传入传出参数
        -writefds:检测的文件描述符的写的集合,委托内核检测哪些文件描述符的写的属性
            -委托内核检测写缓冲区是不是还可以写数据(不满的话就可以写)
        -exceptfds:检测发生异常的文件描述符的集合
        -timeout:设置的超时时间
            struct timeval{
                long tv_sec;
                long tv_usec;
            };
            -NULL :永久阻塞,直到检测到文件描述符有变化
            -tv_sec = 0 tv_usec=0 不阻塞
            -tv_sec > 0 tv_usec>0 阻塞对应的时间

    返回值:-1 失败
            n :检测的集合中有n个文件描述符发生了变化
//将参数文件描述符fd对应的标志位设置为0
void FD_CLR(int fd,fd_set *set);

//判断fd对应的标志位是0还是1,返回值:fd对应的标志位的值,0返回0,1返回1
int FD_ISSET(int fd,fd_set *set);

//将文件描述符fd对应的标志位设置为1
void FD_SET(int fd,fd_set *set);

//fd_set一共有1024bit,全部初始化为0
void FD_ZERO(fd_set *set); 

epoll
创建一个新的epoll实例。在内核中创建一个数据,这个数据有两个比较重要的数据,一个是需要检测的文件描述符的信息(红黑树),还有一个是就绪链表,存放检测到数据发送改变的文件描述符信息(双向链表)

常见的epoll检测事件:
    EPOLLIN
    EPOLLOUT
    EPOLLERR
int poll_create(int size);
    参数:
        size 目前没有意义,随便写一个数,必须大于0

    返回值:
        -1 失败
        >0 文件描述符,操作epoll实例的
//对epoll实例进行管理,添加文件描述符,删除信息,修改信息

int epoll_ctl(int epfd,int op,struct epoll_event *event);
    参数:
        epfd:epoll实例对应的文件描述符
        op: 要进行什么操作 --> 红黑树
            EPOLL_CTL_ADD: 添加
            EPOLL_CTL_MOD: 修改
            EPOLL_CTL_DEL: 删除
        fd :要检测的文件描述符
        event:检测文件描述符什么事情
int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout);
    参数:
        epfd:epoll实例对应文件描述符
        events:传出参数,保存了发送了变化的文件描述符的信息
        maxevents:第二个参数结构体数组的大小
        timeout:阻塞时间
            0 不阻塞
            -1 阻塞,直到有检测到fd数据发生变化解除阻塞
            >0 要阻塞的时长 (毫秒)
    返回值 -1 失败
           >0 返回发生变化的文件描述符的个数
 

11.http协议

超文本传输协议:一个专门在计算机世界里专门在两个点之间传输的文字,图片,视频等超文本数据的约定和规范。首部行里存有各种字段。
http有两种:报文请求和响应报文

例子:
请求报文格式

//请求行,正在请求的对象http版本号
GET /some/dir/page.html HTTP/1.1
//指定的服务器的域名,可以将请求发往同一台服务器上的不同网站
Host : www.someschool.edu
//一个可以复用的TCP连接就建立了,直到客户端或者服务器端主动断开连接
connection:Keep-Alive
//服务器在发完被请求的对象之后关闭连接
connection: close
//浏览器的类型和版本
user-agent : Mozilla/1.0
//声明自己能够接收的请求
Accept:*/*    //都能收
//语言类型
Accept-Language:en-us
//我可以接收什么压缩方式
Accept-Encoding:gzip deflate

响应报文格式

Http/1.1 200 OK
//发送完报文关闭tcp连接
connection:close
//服务器产生该响应并且发送响应报文的时间
date :Tue,09,Aug...
//服务器类型
server:..
//最后对象修改的日期
Last-Modified:
//被发送对象的字节数
content-Length :6180
content-Type:test/html
//采用压缩方式
Contest-Encoding gzip

常见的状态码:
200 OK 请求成功 信息在返回响应的报文之中
301 Move Permanently:请求的对象被永久转移了,新的URL在定义响应报文段的location字段中,浏览器自动重定向新的URL
400 Bad request:一个通用差错编码,指示请求不能被服务器理解
404 Not found:请求的文档不在服务器上
505 Http version not supported 服务器不支持请求报文使用的HTTP协议版本

GET和Post的区别
Get方法的含义是请求服务器获取资源,这个资源可以是静态文本,页面,图片视频等。
而Post方法则是相反的操作。他向URL指定的资源中提交数据,比如说一个人的博客可以留言,我写完留言后点击提交,我的留言就会执行一次post请求。
Get方法是安全的并且是幂等的,也就是说get是一个只读操作,无论执行多少次,服务器上的数据都是安全的,并且每次的结果都是相同的。

Post方法不是安全的并且不是幂等的。 Post因为是新增或者提交数据,会修改服务器上的资源,所以不是安全的。并多次提交数据会执行多次操作创建多个资源,所以不是幂等的。

Get能够被缓存,而post不可以。
Get参数保留在浏览器历史中,而post参数不会保留在浏览器历史中。
当发生数据时,get方法向URL添加数据,URL的数据长度时受限的,而post没有数据长度限制。

Get只允许ASCII编码,而Post没有限制
Get安全性没有post安全性好
Get数据在URL中对所有人是可见的,而在post中数据不会显示在URL中。
Get产生一个TCP数据包,post产生两个TCP数据包。对于get方式的请求,浏览器会把header和data一并发送出去,对于post,浏览器先发送header再发送data。

参考回答:
1.概括
对于get方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据)
而对于post,浏览器先发送header,服务器响应100continue,浏览器再发送data,服务器响应200 ok(返回数据)
2.区别
1.get参数通过url传递,post放在request body中。
2.get请求在url传递的参数是有长度限制的,而post没有。
3.get比post更不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息。
4.get请求只能进行url编码,而post支持多种编码。
5.get请求会主动cache
6.get请求参数会被完整的保留在浏览历史记录里,而post中的参数不会保留
7.get和post本质上都是TCP连接,并无差别。但是由于http的固定和浏览器、服务器的限制,导致他们在应用过程中体现出一些不同。
8.get产生一个TCP数据报,post产生两个TCP数据包

序号 方法 描述
1 GET 发送请求来获得服务器上的资源,请求体中不会包含请求数据,请求数据放在协议头中。另外get支持快取,缓存,可保留书签等。幂等。
2 POST 和get一样很常见,向服务器提交资源让服务器处理,比如提交表单,上传文件等,可能导致建立新的资源或者对原有资源的修改。提交的资源放在请求体中。不支持快取,非幂等,post的数据存放位置由服务器自己决定
3 HEAD 本质上和get一样,但是响应中没有呈现数据,而是http的头信息,主要用来检查资源或者超链接的有效性或是否可以可达,检查网页是否被串改和更新,获取头信息。特别适用在有限的速度和带宽下。
4 PUT 和post类似,html表单不支持,发送资源与服务器,并存储在服务器指定位置,要求客户端事先知道该位置,比如post是在一个集合上(/province),而put是具体在某一个资源上(/province/123)。所以put是安全的,无论请求多少次,都是在123上更改,而post可能请求几次创建了几次资源。幂等
5 DELETE 请求服务器删除某资源,和put都具有破坏性,可能被防火墙拦截。如果是http协议,则无需担心。幂等。
6 CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器,就是把服务器做为跳板,去访问其他网页然后把数据返回回来,连接成功后,就可以正常的get,post。
7 OPTIONS 获取http服务器支持的http请求方法,允许客户端查看服务器的性能,比如ajax跨域时的预检等。
8 TRACE 回显服务器收到的请求。主要用于测试或诊断。一般金庸,防止被恶意攻击或盗取信息。

Cookies和session的区别

  • 登录网站,输入用户名和密码登录,第二天再打开很多情况下就直接打开了,这个时候用到的机制就是cookie。
  • session一个场景就是购物车,添加了商品之后客户端处就可以知道添加了哪些商品,而服务器端如何判别呢,所以也需要存储一些信息,就用到了session。

cookies:当一个web站点通常希望能够识别用户,将内容和用户身份连接起来。当客户端发送http请求的时候,服务器就会在返回的报文中含有set-cookies字段,并且这个字段保存在客户端的硬盘上。这样客户端再次发送请求的时候就会加上自己的cookies,从而服务器就可以识别用户了。可以用在某个站点持久的保存数据。凡是也会造成隐私泄露问题,结合cookies和用户的账户信息,购物信息等。web站点可以知道很多关于用户的信息。cookie存在于客户端,所以也可以伪造。

session:session存在于服务器的一种用来存放用户数据的类Hashtable结构。当浏览器第一次发起请求的时候,服务器就会自动生成session id和hashtable,当第二次发起请求的时候,将前一次服务器响应的session id放在请求中一并发给服务器,这时服务器进行和原来的session id进行对比,就可以找到这个用户的hashtable。

cookie数据保存在客户端,session保存在服务器端。

12.为什么又MAC地址

事实上并不是所有的主机或者路由器都具有链路层地址,而是他们的适配器(网络接口)具有链路层地址。。因此就会有多个网络接口的主机或者路由器将具有多个链路层地址,也就像它具有与之相关联的IP地址一样。

局域网设计是为任意的网络层协议而设计的,而不指示用于IP和因特网,如果适配器指派的时IP地址而不是MAC地址,则适配器不能方便的支持其他的网络层协议。其次网络层地址必须存储在RAM中,在每次适配器移动的时候要重新配置。用MAC地址和IP地址两个地址,用于分别表示物理地址和逻辑地址是有好处的。这样分层可以使网络层与链路层的协议更灵活的替换,网络层不一定要用IP协议,链路层也不一定非用以太网协议

13.ARP协议

ARP协议为IP地址得到对应的硬件地址提供动态映射

ARP只能为同一个子网上的主机和路由器解析IP地址。

ARP(地址解析协议),当主机要发送一个IP包的时候,会先查自己的ARP告诉缓存表,如果查询的IP-MAC的值不存在,主机向网络广播一个ARP请求,这个包里有等待查询的IP地址,而直接收到这份广播的包的所有主机都会查询自己的IP地址,如果收到广播包的某一个主机发现自己符合条件,那就回应一个ARP应答包,源主机拿到ARP应答包后会更新自己的ARP缓存表。源主机根据ARP缓存表准备好数据链路层的数据报发送工作。

点对点链路使用ARP吗?

不使用。

ARP高效运行的关键是什么?

关键是每个主机都有一个ARP告诉缓存。

ARP各个字段以及含义?

帧类型:ARP:0x0806(2)

ARP首部:

硬件类型:硬件地址的类型 1表示以太网地址(2)

协议地址:协议地址的类型,0x0800表示IP地址 (2)


评论
  目录