# go version
go version go1.13.9 linux/amd64
# uname -a
Linux iZ8vbaym9jmge8qd5hlcpiZ 4.15.0-111-generic #112-Ubuntu SMP Thu Jul 9 20:32:34 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
http服务器如下:
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
_ "net/http/pprof"
)
func main() {
h2 := func(w http.ResponseWriter, _ *http.Request) {
time.Sleep(2 * time.Second)
fmt.Println("555555")
if _, err := w.Write(make([]byte, 9999)); err != nil {
fmt.Println("---=====: ", err.Error(), syscall.EPIPE == err)
return
}
}
go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()
http.HandleFunc("/endpoint", h2)
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGPIPE)
go func() {
sig := <-sigs
fmt.Println("6666666666", sig.String())
fmt.Println(sig)
}()
log.Fatal(http.ListenAndServe(":8888", nil))
}
1,通过Unix域套接字
curl请求curl 127.0.0.1:8888/endpoint -m 0.2
结果:
555555
---=====: write tcp 127.0.0.1:8888->127.0.0.1:33794: write: broken pipe false
6666666666 broken pipe
broken pipe
curl请求:curl 47.92.3.20:8888/endpoint -m 0.2
get result:555555
去的netpoll处理unix域套接字和tcp套接字在不同的方式?我看不出netpoll代码有什么不同。
在连接处理方面找不到任何差异,因为两种情况的处理方式相同。这不是Go特有的,在unix套接字中,连接的写端可以立即检测连接何时关闭。
在TCP套接字中,没有办法立即检测到已关闭的连接。您可以等待recv调用返回0(或go中的io.EOF
),这是在某些情况下发生的情况,也是Request.Context
被取消的原因,但它不能立即覆盖连接断开的情况。当正在发送数据的远程主机离开时,您所能做的就是继续写入,直到TCP堆栈接收到指示连接不再可用的RST或ICMP消息。一旦发生这种情况,在大多数类unix系统上,您将从系统获得相同的broken pipe
错误。