前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >超级肝文-深入剖析客户端出现connect reset by peer报错相关的技术知识

超级肝文-深入剖析客户端出现connect reset by peer报错相关的技术知识

作者头像
公众号-利志分享
发布2022-04-25 09:38:13
2.6K0
发布2022-04-25 09:38:13
举报
文章被收录于专栏:利志分享

关于http请求的报错:connect reset by peer,我相信大家应该都有所见过。今天我来剖析一下这个报错情况以及整理一下相关技术知识。

案例

报错原因:服务端断开连接,但是客户端还是复用之前的连接进行请求,则会报此错误。如果是http1协议和http1.1协议中出现此类报错,则是开启:Keep-Alive,http1.1则是默认开启Keep-Alive的,如果是用的http2协议的话,则报错是因为复用连接。

复现方式:由于这个报错基于tcp协议来实现比较方便,我这里就采用go来实现server端,客户端,并且复现报错。

1 实现server端代码

代码语言:javascript
复制
package main

import (
    "log"
    "net"
    "os"
)

func server() {
    listener, err := net.Listen("tcp", ":8090")
    if err != nil {
        log.Fatal(err)
    }

    defer listener.Close()
    conn, err := listener.Accept()
    if err != nil {
        log.Fatal("server", err)
        os.Exit(1)
    }

    log.Printf("server close start")
    conn.Close()
    log.Printf("server close end")
}

func main() {
     server()
}

2 实现客户端代码

代码语言:javascript
复制
package main

import (
    "errors"
    "log"
    "net"
    "syscall"
    "time"
)

func client() {
    conn, err := net.Dial("tcp", "124.221.97.119:8090")
    if err != nil {
        log.Fatal("client", err)
    }

    if _, err := conn.Write([]byte("ab")); err != nil {
        log.Printf("client: %v", err)
    }

    time.Sleep(1 * time.Second) // wait for close on the server side

    data := make([]byte, 1)
    if _, err := conn.Read(data); err != nil {
        log.Printf("client: %v", err)
        if errors.Is(err, syscall.ECONNRESET) {
            log.Print("This is connection reset by peer error")
        }
    }
}

func main() {
    client()
}

3 启动server端

server端在124.221.97.119(这个我买的临时的机器,大家不要对我这个进行进行攻击哦)这个机器上。

4 执行客户端

客户端在另外一个机器上,然后server端会断开,客户端则会报如下的错误:

代码语言:javascript
复制
2022/03/27 19:59:20 client: read tcp 10.23.165.46:24972->124.221.97.119:8090: read: connection reset by peer
2022/03/27 19:59:20 This is connection reset by peer error

5 tcpdump抓包结果

代码语言:javascript
复制
20:11:23.580281 IP xx.xx.xx.xx.24976 > 10.0.16.6.8090: Flags [S], seq 3946141306, win 64952, options [mss 1412,sackOK,TS val 3205380659 ecr 0,nop,wscale 7], length 0
20:11:23.580293 IP 10.0.16.6.8090 > xx.xx.xx.xx.24976: Flags [S.], seq 298221640, ack 3946141307, win 28960, options [mss 1460,sackOK,TS val 2496773398 ecr 3205380659,nop,wscale 7], length 0
20:11:23.588677 IP xx.xx.xx.xx.24976 > 10.0.16.6.8090: Flags [.], ack 1, win 508, options [nop,nop,TS val 3205380668 ecr 2496773398], length 0
20:11:23.588698 IP xx.xx.xx.xx.24976 > 10.0.16.6.8090: Flags [P.], seq 1:3, ack 1, win 508, options [nop,nop,TS val 3205380668 ecr 2496773398], length 2
20:11:23.588703 IP 10.0.16.6.8090 > xx.xx.xx.xx.24976: Flags [.], ack 3, win 227, options [nop,nop,TS val 2496773406 ecr 3205380668], length 0
20:11:23.589014 IP 10.0.16.6.8090 > xx.xx.xx.xx.24976: Flags [R.], seq 1, ack 3, win 227, options [nop,nop,TS val 2496773407 ecr 3205380668], length 0

截图如下:

好了,上面的报错我们已经给大家复现出来了,下面我们来看一下另外一种情况,假如我们直接执行上面的client代码,会得到如下的报错:

代码语言:javascript
复制
2022/03/27 20:20:06 clientdial tcp 124.221.97.119:8090: connect: connection refused

exit status 1

这个时候的关于tcpdump抓包则会出现如下信息:

代码语言:javascript
复制
20:23:52.448494 IP xx.xx.xx.xx.25010 > 10.0.16.6.8090: Flags [S], seq 2442872680, win 64952, options [mss 1412,sackOK,TS val 3206129524 ecr 0,nop,wscale 7], length 0

20:23:52.448524 IP 10.0.16.6.8090 > xx.xx.xx.xx.25010: Flags [R.], seq 0, ack 2442872681, win 0, length 0

关于connection refused的报错,tcp协议直接会返回RST包给客户端,我们看下下面的图。

关于connect reset by peer,tcp协议响应了RST包,造成客户端报错。具体如图:

关于上面的出现的问题,我们需要学习如下知识,才能让我们更好的分析问题,复现问题,解决好问题。

1 理解tcpdump的输出

代码语言:javascript
复制
20:23:52.448494 IP xx.xx.xx.xx.25010 > 10.0.16.6.8090: Flags [S], seq 2442872680, win 64952, options [mss 1412,sackOK,TS val 3206129524 ecr 0,nop,wscale 7], length 0

内容结构

第一列:时分秒毫秒 20:23:52.448494

第二列:网络协议 IP

第三列:发送方的ip地址+端口号,其中xx.xx.xx.xx是 ip,而25010是端口号

第四列:箭头 >, 表示数据流向

第五列:接收方的ip地址+端口号,其中 10.0.16.6是 ip,而8090是端口号

第六列:冒号

第七列:数据包内容,包括Flags 标识符,seq 号,ack 号,win 窗口,数据长度 length,其中 [P.] 表示 PUSH 标志位为 1,更多看Flag标识符讲解。

Flags 标识符

[S] : SYN(开始连接)

[P] : PSH(推送数据)

[F] : FIN (结束连接)

[R] : RST(重置连接)

[.] : 没有 Flag,由于除了 SYN 包外所有的数据包都有ACK,所以一般这个标志也可表示 ACK

2 OSI 七层模型与TCP/IP五层模型

关于分层的知识,如下。

3 HTTP协议

HTTP协议基于TCP/IP的传输流图解:

一个HTTPS请求的流程图解

tcp建立图解

总结

1:要学会从问题出发,学习相关问题的技术知识,深入剖析知识,这样更容易成长。

2:connect reset by peer的报错是因为出现RST重置连接引发的报错。

参考文献

https://gosamples.dev/connection-reset-by-peer/#:~:text=Typically%2C%20you%20can%20see%20the,connection%20to%20be%20forcibly%20closed.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 利志分享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档