草庐IT

计算机网络实验---Wireshark 实验

lili要努力 2023-09-02 原文

数据链路层
实作一/熟悉 Ethernet 帧结构
实作二/了解子网内/外通信时的 MAC 地址
实作三/掌握 ARP 解析过程

网络层
实作一 /熟悉 IP 包结构
实作二 IP 包的分段与重组
实作三 考察 TTL 事件

传输层
实作一 熟悉 TCP 和 UDP 段结构
实作二 分析 TCP 建立和释放连接

应用层
实作一 了解 DNS 解析
实作二 了解 HTTP 的请求和应答

总结

数据链路层

实作一/熟悉 Ethernet 帧结构

实验目的:使用 Wireshark 任意进行抓包,熟悉 Ethernet 帧的结构,如:目的 MAC、源 MAC、类型、字段等。

问题

你会发现 Wireshark 展现给我们的帧中没有校验字段,请了解一下原因。

在 Wireshark 中,校验字段通常被称为帧校验和(FCS)。帧校验和是一个数据链路层功能,用于检测数据帧中的错误。它通常在帧的末尾添加,但是在 Wireshark 中,它并不总是显示。

这是因为,有时候帧校验和可能已经被删除,例如在路由器中。在这种情况下,Wireshark 将不会显示帧校验和字段。

此外,有些帧类型可能不包含帧校验和字段。例如,以太网帧通常包含帧校验和,但是以太网 II 帧并不包含帧校验和字段。因此,如果您在 Wireshark 中捕获的帧是以太网 II 帧,则不会看到帧校验和字段。

总之,Wireshark 中没有显示帧校验和字段的原因是,帧校验和可能已经被删除,或者帧类型本身不包含帧校验和字段。

实作二/了解子网内/外通信时的 MAC 地址

ping 你旁边的计算机(同一子网),同时用 Wireshark 抓这些包(可使用 icmp 关键字进行过滤以利于分析),记录一下发出帧的目的 MAC 地址以及返回帧的源 MAC 地址是多少?这个 MAC 地址是谁的?

IP为10.161.91.228主机的信息如下图所示:

然后我们进行抓包进行解析相关数据,如下图所示:

由上图可以得出访问本子网的计算机时,目的 MAC 就是该主机的。

然后 ping 124.220.194.38 (或者本子网外的主机都可以),同时用 Wireshark 抓这些包(可 icmp 过滤),记录一下发出帧的目的 MAC 地址以及返回帧的源 MAC 地址是多少?这个 MAC 地址是谁的?

验证结果

由上图可知,抓包获得的MAC地址并不是我的服务器上的MAC地址,于是我们可以tracert进行追踪,查看抓取的MAC地址为谁的,如下图所示。

我们可以再次ping 10.160.255.254,然后再次进行抓包,如下图所示。

由上图可以发现,目的MAC地址和我们首次抓取的目的MAC一样,由此得知,此MAC地址为IP地址为10.160.255.254主机的MAC地址,也即是网关的MAC地址

再次 ping www.cqjtu.edu.cn (或者本子网外的主机都可以),同时用 Wireshark 抓这些包(可 icmp 过滤),记录一下发出帧的目的 MAC 地址以及返回帧的源 MAC 地址又是多少?这个 MAC 地址又是谁的?

问题

通过以上的实验,你会发现:

  1. 访问本子网的计算机时,目的 MAC 就是该主机的
  2. 访问非本子网的计算机时,目的 MAC 是网关的

请问原因是什么?

非本子网的信息必定经由子网网关发送给本机,同理本机发送到非本子网的信息的下个地址必定是网关的mac地址。而且MAC地址是数据链路层的地址,数据链路层是只与其直接相连的节点打交道的。当访问非本子网的计算机时,必定通过各节点的路由器进行存储转发,其本机相邻的主机即为网关,故目的MAC地址为网关的。而本子网内的可以直接到达,目的MAC地址是目的主机的。

实作三/掌握 ARP 解析过程

为防止干扰,先使用 arp -d * 命令清空 arp 缓存

ping 你旁边的计算机(同一子网),同时用 Wireshark 抓这些包(可 arp 过滤),查看 ARP 请求的格式以及请求的内容,注意观察该请求的目的 MAC 地址是什么。再查看一下该请求的回应,注意观察该回应的源 MAC 和目的 MAC 地址是什么。

首先我的MAC地址为:

再次使用 arp -d * 命令清空 arp 缓存

然后 ping qige.io (或者本子网外的主机都可以),同时用 Wireshark 抓这些包(可 arp 过滤)。查看这次 ARP 请求的是什么,注意观察该请求是谁在回应。

问题

通过以上的实验,你应该会发现,

  1. ARP 请求都是使用广播方式发送的
  2. 如果访问的是本子网的 IP,那么 ARP 解析将直接得到该 IP 对应的 MAC;如果访问的非本子网的 IP, 那么 ARP 解析将得到网关的 MAC。

请问为什么?

对于问题1,由于在本地的 ARP 缓存表中查询不到其 IP 对应的 MAC 地址,为了获取其 MAC 地址,必须让该网络下所有的计算机都收到 ARP 请求,因此必须使用广播方式进行发送。

对于问题2,如果访问本子网的 IP,由于可以直接到达,故广播发送 ARP 请求后,就能得到该 IP 对应的 MAC 地址,但是访问非本子网的 IP 时,由于非本子网的信息必定经由子网网关发送给本机,而且MAC地址是数据链路层的地址,数据链路层是只与其直接相连的节点打交道的。当访问非本子网的计算机时,必定通过各节点的路由器进行存储转发,其本机相邻的主机即为网关,故 ARP 解析将得到网关的 MAC 地址。

网络层

实作一 /熟悉 IP 包结构

使用 Wireshark 任意进行抓包(可用 ip 过滤),熟悉 IP 包的结构,如:版本、头部长度、总长度、TTL、协议类型等字段。

问题

为提高效率,我们应该让 IP 的头部尽可能的精简。但在如此珍贵的 IP 头部你会发现既有头部长度字段,也有总长度字段。请问为什么?

方便了对数据链路层的使用。并且 IP 头部中有头部长度字段和总长度字段可以提高效率。头部长度字段可以帮助设备快速定位数据包中的其他字段,而总长度字段则可以帮助设备确定数据包的结束位置,当长度超过1500B时就会被返回链路层进行分段,从而避免读取到无效数据。

实作二 IP 包的分段与重组

根据规定,一个 IP 包最大可以有 64K 字节。但由于 Ethernet 帧的限制,当 IP 包的数据超过 1500 字节时就会被发送方的数据链路层分段,然后在接收方的网络层重组。

缺省的,ping 命令只会向对方发送 32 个字节的数据。我们可以使用 ping 202.202.240.16 -l 2000 命令指定要发送的数据长度。此时使用 Wireshark 抓包(用 ip.addr == 202.202.240.16 进行过滤),了解 IP 包如何进行分段,如:分段标志、偏移量以及每个包的大小等

为什么偏移量是1480,很简单。由于MTU为1500,IP包的首部长度为20,故数据部分为1480,故下一个偏移量从1480开始。

问题

分段与重组是一个耗费资源的操作,特别是当分段由传送路径上的节点即路由器来完成的时候,所以 IPv6 已经不允许分段了。那么 IPv6 中,如果路由器遇到了一个大数据包该怎么办?

遇到大数据包,就往回报包过大,并丢弃,保证了路由器专注于解决路径问题,包被切成了1500左右大小的小包

实作三 考察 TTL 事件

在 IP 包头中有一个 TTL 字段用来限定该包可以在 Internet上传输多少跳(hops),一般该值设置为 64、128等。

在验证性实验部分我们使用了 tracert 命令进行路由追踪。其原理是主动设置 IP 包的 TTL 值,从 1 开始逐渐增加,直至到达最终目的主机。

请使用 tracert www.baidu.com 命令进行追踪,此时使用 Wireshark 抓包(用 icmp 过滤),分析每个发送包的 TTL 是如何进行改变的,从而理解路由追踪原理。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jsCRLPPL-1672289634793)(https://teng-1310538376.cos.ap-chongqing.myqcloud.com/3718/202212051552304.png)]

主机发的报文所设置的生存周期在从1开始不断地变大,因为TTL每经过一个路由器的时候都会被减一,当TTL等于0的时候就会被抛弃,并且返回一个超时的ICMP数据包。这时我们就可以知道路由结点的地址了。

问题

在 IPv4 中,TTL 虽然定义为生命期即 Time To Live,但现实中我们都以跳数/节点数进行设置。如果你收到一个包,其 TTL 的值为 50,那么可以推断这个包从源点到你之间有多少跳?

至少50跳。

原因(为什么是至少50):可以推断这个数据包从源点到我之间经过了 49 个路由器,并且因为一个路由器可能会将数据包转发到多个不同的位置。例如,一个路由器可能会将数据包转发到多个子网,或者将数据包转发到多个不同的路由器。因此,数据包实际上可能经过的路径比跳数要多。

传输层

实作一 熟悉 TCP 和 UDP 段结构

  1. 用 Wireshark 任意抓包(可用 tcp 过滤),熟悉 TCP 段的结构,如:源端口、目的端口、序列号、确认号、各种标志位等字段

  • 紧急位URG。URG= 1时,表明紧急指针字段有效。它告诉系统报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。但URG需要和紧急指针配套使用,即数据从第一个字节到紧急指针所指字节就是紧急数据
  • 确认位ACK。只有当ACK= 1时确认号字段才有效。当ACK=0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1。
  • 推送位PSH (Push)。 接收TCP收到PSH=1的报文段,就尽快地交付给接收应用进程而不再等到整个缓存都填满后再向上交付。
  • 复位位RST (Reset)。RST=1时,表明TCP连接中出现严重差错(如主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
  • 同步位SYN。同步SYN= 1表示这是一个连接请求或连接接收报文。当SYN=1, ACK=0时,表明这是一个连接请求报文,对方若同意建立连接,则在响应报文中使用SYN=1, ACK=1。即SYN= 1表示这是一个连接请求或连接接收报文。
  • 终止位FIN (Finish)。用来释放一个连接。FIN= 1表明此报文段的发送方的数据已发送完毕,并要求释放传输连接。
  1. 用 Wireshark 任意抓包(可用 udp 过滤),熟悉 UDP 段的结构,如:源端口、目的端口、长度等。

问题

由上大家可以看到 UDP 的头部比 TCP 简单得多,但两者都有源和目的端口号。请问源和目的端口号用来干什么?

源端口就是指本地端口,目的端口就是远程端口,源端口就是本机程序用来发送数据的端口,目的端口就是对方主机用哪个端口接收,通过记录收发双方的端口,从而实现两者之间的通信并且,源端口和目的端口是用来确认某一个应用程序,IP 只能到达子网网关,MAC 地址到达子网下的指定主机,而端口号是达到主机上的某个应用程序。

实作二 分析 TCP 建立和释放连接

  1. 打开浏览器访问 qige.io 网站,用 Wireshark 抓包(可用 tcp 过滤后再使用加上 Follow TCP Stream),不要立即停止 Wireshark 捕获,待页面显示完毕后再多等一段时间使得能够捕获释放连接的包。

  1. 请在你捕获的包中找到三次握手建立连接的包,并说明为何它们是用于建立连接的,有什么特征。

TCP 是一种双向通信协议,这意味着任何一端都应该能够可靠地发送数据。双方都需要建立一个序列号,双方都需要确认对方的序列号。TCP三次握手的目的是建立可靠的通信信道。通信,简单来说就是数据的发送和接收。

那么client要与server建立TCP连接,需要通过握手确认这四件事情

1.server需要确认它可以从client接收数据包;

2.client需要确认它可以从server接收数据包;

3.client需要确认一件事:server可以从client接收数据包;

4.server需要确认一件事:client可以从server接收数据包。

而三次握手最主要的目的就是双方确认自己与对方的发送和接收是正常的


  1. 请在你捕获的包中找到四次挥手释放连接的包,并说明为何它们是用于释放连接的,有什么特征。

此次用www.baidu.com作为演示进行测试,测试如下:

问题一

去掉 Follow TCP Stream,即不跟踪一个 TCP 流,你可能会看到访问 qige.io 时我们建立的连接有多个。请思考为什么会有多个连接?作用是什么?

这是因为网络协议为了提高传输效率,在传输过程中使用了一些技术来提高效率。

例如,在 HTTP 协议中,服务器可以在一个连接中同时传输多个资源,这样就可以避免浏览器不断地发起连接请求,从而提高传输效率。

此外,在访问网站时,浏览器也可能会为了提高效率,同时发起多个连接来下载资源。这样就可以并行下载多个资源,从而提高传输效率。

我们上面提到了释放连接需要四次挥手,有时你可能会抓到只有三次挥手。原因是什么?

具体原因可能有很多,可能是网络中某个设备出现故障,导致某个报文丢失;也可能是某个设备由于某些原因,在发送 FIN 报文之前就关闭了连接;或者是计算机在断开连接之前,被电源关闭或系统崩溃了,导致四次挥手的过程没有正常完成;也可能是服务器向客户端发送断开连接和回复同意断开连接合成一次挥手。

应用层

实作一 了解 DNS 解析

  1. 先使用 ipconfig /flushdns 命令清除缓存,再使用 nslookup qige.io 命令进行解析,同时用 Wireshark 任意抓包(可用 dns 过滤)。

  1. 你应该可以看到当前计算机使用 UDP,向默认的 DNS 服务器的 53 号端口发出了查询请求,而 DNS 服务器的 53 号端口返回了结果。

  1. 可了解一下 DNS 查询和应答的相关字段的含义

DNS查询和应答报文的格式如下:

16位标识字段用于标记一对DNS查询和应答,以此区分一个DNS应答是哪个DNS查询的回应。

16位标志字段用于协商具体的通信方式和反馈通信状态。

DNS报文头部的16位标志字段的细节如图

  1. QR:查询/应答标志。0表示这是一个查询报文,1表示这是一个应答报文
  2. opcode,定义查询和应答的类型。0表示标准查询,1表示反向查询(由IP地址获得主机域名),2表示请求服务器状态
  3. AA,授权应答标志,仅由应答报文使用。1表示域名服务器是授权服务器
  4. TC,截断标志,仅当DNS报文使用UDP服务时使用。因为UDP数据报有长度限制,所以过长的DNS报文将被截断。1表示DNS报文超过512字节,并被截断
  5. RD,递归查询标志。1表示执行递归查询,即如果目标DNS服务器无法解析某个主机名,则它将向其他DNS服务器继续查询,如此递归,直到获得结果并把该结果返回给客户端。0表示执行迭代查询,即如果目标DNS服务器无法解析某个主机名,则它将自己知道的其他DNS服务器的IP地址返回给客户端,以供客户端参考
  6. RA,允许递归标志。仅由应答报文使用,1表示DNS服务器支持递归查询
  7. zero,这3位未用,必须设置为0
  8. rcode,4位返回码,表示应答的状态。常用值有0(无错误)和3(域名不存在)

接下来的4个字段则分别指出DNS报文的最后4个字段的资源记录数目。对查询报文而言,它一般包含1个查询问题,而应答资源记录数,授权资源记录数和额外资源记录数则为0.应答报文的应答资源记录数则至少为1,而授权资源记录数和额外资源记录数可为0或非0。

查询问题的格式:

如图所示,查询名以一定的格式封装了要查询的主机域名。16位查询类型表示如何执行查询操作,常见的类型有如下几种:

  1. 类型A,值是1,表示获取目标主机的IP地址
  2. 类型CNAME,值是5,表示获得目标主机的别名
  3. 类型PTR,值是12,表示反向查询

应答字段,授权字段和额外信息字段都使用资源记录(Resource Record,RR)格式。

资源记录格式:

  1. 32位域名是该记录中与资源对应的名字,其格式和查询问题中的查询名字段相同。16位类型和16位类字段的含义也与DNS查询问题的对应字段相同。
  2. 32位生存时间表示该查询记录结果可被本地客户端程序缓存多长时间,单位是秒
  3. 16位资源数据长度字段和资源数据字段的内容取决于类型字段。对类型A而言。资源数据是32位的IPv4地址,而资源数据长度则为4(以字节为单位)

问题

你可能会发现对同一个站点,我们发出的 DNS 解析请求不止一个,思考一下是什么原因?

这是因为浏览器在访问网站时,不仅会加载网站的主页,还会加载其他资源,例如图片、视频、广告等等。这些资源可能来自于不同的域名,因此浏览器会对这些域名进行 DNS 解析,以获取对应的 IP 地址。并且在 DNS 解析请求时会进行递归+迭代的方式进行查询,请求也可能不止一个。此外,浏览器在访问网站时,还会缓存 DNS 解析结果,以便在下次访问时使用。如果缓存中有相应的域名解析结果,就不会再发起 DNS 解析请求。所以,如果你访问的是一个经常访问的网站,可能会发现 DNS 解析请求较少。

实作二 了解 HTTP 的请求和应答

  1. 打开浏览器访问 qige.io 网站,用 Wireshark 抓包(可用http 过滤再加上 Follow TCP Stream),不要立即停止 Wireshark 捕获,待页面显示完毕后再多等一段时间以将释放连接的包捕获。

由于qige.io抓取不到相关包,我抓取了重庆交通大学信息科学与工程学院相关包,如下所示:

  1. 请在你捕获的包中找到 HTTP 请求包,查看请求使用的什么命令,如:GET, POST。并仔细了解请求的头部有哪些字段及其意义。

  1. 请在你捕获的包中找到 HTTP 应答包,查看应答的代码是什么,如:200, 304, 404 等。并仔细了解应答的头部有哪些字段及其意义。

1xx 表示接收信息且正在处理
2xx 表示正常处理完毕,200——OK
3xx 表示正常处理外的附加操作,304——Not Modified没有修改,在缓存中有、302 Found 表示临时重定向、301 Moved Permanently表示永久重定向
4xx 表示客户端请求有误,服务器无法处理,404——Not Found,403——Forbidden、401 Unauthorized 表示未认证
5xx 表示服务器存在异常,502——Bad Gateway、500 Internal Server Error表示服务器故障、503 Service Unavailiable表示服务器繁忙

✍ 建议:

HTTP 请求和应答的头部字段值得大家认真的学习,因为基于 Web 的编程中我们将会大量使用。如:将用户认证的令牌信息放到头部,或者把 cookie 放到头部等。

用户认证中常用的是使用 jwt,可以放在头部一个 key 为 Authoriaztion 的信息,然后 value 为用户的 token 值,并且具有过期时间,每次退出后都会重新计算用户的 token 值,这是 Web 登录常用的一种手段。

问题

刷新一次 qige.io 网站的页面同时进行抓包,你会发现不少的 304 代码的应答,这是所请求的对象没有更改的意思,让浏览器使用本地缓存的内容即可。那么服务器为什么会回答 304 应答而不是常见的 200 应答?

这是因为服务器希望节省带宽资源,使浏览器尽可能地使用本地缓存。

当浏览器向服务器发出请求时,会携带一些信息,例如 If-Modified-Since 头域,这个头域告诉服务器浏览器的缓存的最后修改时间。如果服务器认为浏览器的缓存内容是最新的,就会返回 304 应答,让浏览器使用本地缓存的内容。如果服务器认为浏览器的缓存内容不是最新的,就会返回 200 应答,并附带最新的内容。

使用本地缓存可以节省带宽资源,同时也可以提高用户体验,因为浏览器不需要再从服务器中获取内容,而是直接使用本地缓存的内容。但是,如果服务器的内容发生了更新,那么本地缓存的内容就不是最新的,就需要从服务器中获取最新的内容。

总的来说,使用缓存是一种常见的优化手段,可以节省带宽资源,提高用户体验。但是,也要注意缓存的更新问题,确保用户使用的是最新的内容。

总结

通过对Wireshark实验的学习,学习到了Wireshar抓包工具的使用。并且通过理论学习相关的各个数据的头部,并且通过Wireshark理论进行抓包实际操作,使对网络各个层的协议字段数据头部认识更加清楚,理解更加深刻。并且通过抓包更加理解了相关协议的执行过程,如ARP协议解析过程、TCP建立和释放过程、DNS解析过程、HTTP的请求与应答等等,这些都是计算机网络中比较重要的部分。总之,Wireshark是在学习计算机网络中必不可少的软件,可以帮助我们很好的理解与解析相关协议与相关包结构。

有关计算机网络实验---Wireshark 实验的更多相关文章

  1. ruby-on-rails - 使用一系列等级计算字母等级 - 2

    这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

  2. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  3. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  4. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  5. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  6. ruby - 使用 Ruby,计算 n x m 数组的每一列中有多少个 true 的简单方法是什么? - 2

    给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in

  7. arrays - 计算数组中的匹配元素 - 2

    给定两个大小相等的数组,如何找到不考虑位置的匹配元素的数量?例如:[0,0,5]和[0,5,5]将返回2的匹配项,因为有一个0和一个5共同;[1,0,0,3]和[0,0,1,4]将返回3的匹配项,因为0有两场,1有一场;[1,2,2,3]和[1,2,3,4]将返回3的匹配项。我尝试了很多想法,但它们都变得相当粗糙和令人费解。我猜想有一些不错的Ruby习惯用法,或者可能是一个正则表达式,可以很好地回答这个解决方案。 最佳答案 您可以使用count完成它:a.count{|e|index=b.index(e)andb.delete_at

  8. ruby - 检查网络文件是否存在,而不下载它? - 2

    是否可以在不实际下载文件的情况下检查文件是否存在?我有这么大的(~40mb)文件,例如:http://mirrors.sohu.com/mysql/MySQL-6.0/MySQL-6.0.11-0.glibc23.src.rpm这与ruby​​不严格相关,但如果发件人可以设置内容长度就好了。RestClient.get"http://mirrors.sohu.com/mysql/MySQL-6.0/MySQL-6.0.11-0.glibc23.src.rpm",headers:{"Content-Length"=>100} 最佳答案

  9. ruby - 404 未找到,但可以从网络浏览器正常访问 - 2

    我在这方面尝试了很多URL,在我遇到这个特定的之前,它们似乎都很好:require'rubygems'require'nokogiri'require'open-uri'doc=Nokogiri::HTML(open("http://www.moxyst.com/fashion/men-clothing/underwear.html"))putsdoc这是结果:/Users/macbookair/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/open-uri.rb:353:in`open_http':404NotFound(OpenURI::HT

  10. ruby-on-rails - 如何计算 Ruby/Rails 中 JSON 对象的数量 - 2

    Ruby中如何“一般地”计算以下格式(有根、无根)的JSON对象的数量?一般来说,我的意思是元素可能不同(例如“标题”被称为其他东西)。没有根:{[{"title":"Post1","body":"Hello!"},{"title":"Post2","body":"Goodbye!"}]}根包裹:{"posts":[{"title":"Post1","body":"Hello!"},{"title":"Post2","body":"Goodbye!"}]} 最佳答案 首先,withoutroot代码不是有效的json格式。它将没有包

随机推荐