原文: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
- 如果讀端關閉連接,寫端繼續寫,第一次寫,會收到RST,再寫,報錯