【轉】3種TCP連接異常的情況。


原文:http://www.bubuko.com/infodetail-3022082.html

 

 

 

 

 

 

----------------------------------

 

本文介紹3種TCP連接異常的情況。

1.server端沒有啟動,client嘗試連接

./client
dial failed: dial tcp 127.0.0.1:8080: connect: connection refused

通過tcpdump抓包,可以看到當server沒有啟動的時候,client向server8080端口發送數據后,client端會收到RST。

2.client端讀數據,突然異常退出或直接close連接

2.1 准備

server

server等待連接,如果有client連接過來,連接建立后,會向client發送數據。

server代碼如下:

package main

import (
        "net"
        "log"
        "time"
)


func main() {

        addr := "0.0.0.0:8080"

        tcpAddr, err := net.ResolveTCPAddr("tcp",addr)

        if err != nil {
                log.Fatalf("net.ResovleTCPAddr fail:%s", addr)
        }

        listener, err := net.ListenTCP("tcp", tcpAddr)
        if err != nil {
                log.Fatalf("listen %s fail: %s", addr, err)
        } else {

                log.Println("rpc listening", addr)
        }


        for {
                conn, err := listener.Accept()
                if err != nil {
                        log.Println("listener.Accept error:", err)
                        continue
                }

                go handleConnection(conn)

        }

}


func handleConnection(conn net.Conn) {

        defer conn.Close()

        var buffer []byte = []byte("You are welcome. I'm server.")


        for {

                time.Sleep(3*time.Second)
                n, err := conn.Write(buffer)
                if err != nil {
                        log.Println("Write error:", err)
                        break
                }
                log.Println("send:", n)

        }

        log.Println("connetion end")

}

client

client端連接server,並接收server端數據。

client代碼如下:

package main


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

func main() {

        conn, err := net.Dial("tcp", "127.0.0.1:8080")
        if err != nil {
                log.Println("dial failed:", err)
                os.Exit(1)
        }
        defer conn.Close()


        buffer := make([]byte, 512)

        for {

                n, err := conn.Read(buffer)
                if err != nil {
                        log.Println("Read failed:", err)
                        return
                }

                log.Println("count:", n, "msg:", string(buffer))
        }

}

2.2 操作步驟如下

(1).client與server建立連接后

(2).啟動server

(3).啟動client

(4).client異常退出

client 進程異常退出或者close連接,都會發送FIN。

 ./client
2019/04/13 19:45:44 count: 28 msg: You are welcome. I'm server.
^C

19:45:44后, Ctrl + C 退出

(5).查看server端報錯

./server
2019/04/13 19:45:17 rpc listening 0.0.0.0:8080



2019/04/13 19:45:44 send: 28
2019/04/13 19:45:47 send: 28
2019/04/13 19:45:50 Write error: write tcp 127.0.0.1:8080->127.0.0.1:62785: write: broken pipe
2019/04/13 19:45:50 connetion end

client退出后,server發送了兩次數據,第一次沒有報錯,第二次報錯:

2019/04/11 15:49:04 send: 28
2019/04/11 15:49:07 Write error: write tcp 127.0.0.1:8080->127.0.0.1:54631: write: broken pipe

通過tcpdump抓包可以發現,client退出后,server第一次發送給client,client返回給server RST。
第二次在這個RST的連接上,server繼續發送,出現broken pipe。

3.server端寫數據,突然異常退出或直接close連接

3.1 准備

server、client代碼同上。

3.2 操作步驟

(1).client與server建立連接后

(2).啟動server

(3).啟動client

(4).server異常退出

server 進程異常退出或者close連接,都會發送FIN。

./server
2019/04/11 15:58:46 rpc listening 0.0.0.0:8080
2019/04/11 15:58:54 send: 28
2019/04/11 15:58:57 send: 28
^C

(5).查看client報錯

./client
2019/04/11 15:58:54 count: 28 msg: You are welcome. I'm server.
2019/04/11 15:58:57 count: 28 msg: You are welcome. I'm server.
2019/04/11 15:58:58 Read failed: EOF

4.總結

  • 如果server端沒有啟動,client嘗試連接時,會收到RST。

  • 連接建立后,如果讀端或者寫端關閉連接,具體分兩種情況:

    • 如果讀端關閉連接,寫端繼續寫,第一次寫,會收到RST,再寫,報錯broken pipe
    • 如果寫端關閉連接,讀端繼續讀,報錯EOF


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM