New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net: TCP server did NOT Close Conn when I close connection #29989
Comments
Defer statements execute when the surrounding function returns or encounters a panic. Yours is inside an infinite for loop so it will never execute the close. You should move this logic to your handle function. |
@bruston Thank you first, |
As far as I know, at least on Linux and Mac, there is no way to get notified when the connection is closed, except reading from the socket and checking for a 0 byte read (which is converted to a (0, io.EOF) return value in Go). You could enable keep alive on each connection via TCPConn.SetKeepAlive. This would ensure that the socket will be closed by the OS after some time, but you would still need to detect this by reading from the socket and closing the |
If the client closes the connection properly it should work just fine so long as you check and handle your read errors. If the connection is not properly closed (internet connection dies, router gets unplugged, etc) things get a bit more tricky. You can set timeout deadlines for your read operations: https://golang.org/pkg/net/#TCPConn.SetReadDeadline and then close the connection yourself on a timeout error. You might also be able to use KeepAlive: https://golang.org/pkg/net/#TCPConn.SetKeepAlive or implement your own kind of health check. This doesn't seem like a bug, rather just the way TCP works. If you have more questions you're more than welcome to ask for assistance on any of the mediums listed here: https://github.com/golang/go/wiki/Questions |
I don't see any actual bug here, so closing. |
@ianlancetaylor yes, actually there is not a bug, but I want Close those TCP closed connection automatically. |
Here is the code to clean package main
import (
"fmt"
"net"
"os"
"os/exec"
"strconv"
"regexp"
"time"
"strings"
"github.com/liuzheng/golog"
)
var lsofout = ""
func main() {
l, err := net.Listen("tcp", ":1234")
if err != nil {
fmt.Println("Error listening: ", err)
os.Exit(1)
}
defer l.Close()
ticker := time.NewTicker(time.Second * 5)
go func() {
for range ticker.C {
lsof := exec.Command("lsof", "-p", strconv.Itoa(os.Getpid()), "-a", "-i", "tcp")
grep := exec.Command("grep", "CLOSE_WAIT")
lsofOut, _ := lsof.StdoutPipe()
lsof.Start()
grep.Stdin = lsofOut
out, _ := grep.Output()
lsofout = string(out)
}
}()
for {
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err)
os.Exit(1)
}
fmt.Printf("Start to receive message %s -> %s \n", conn.RemoteAddr(), conn.LocalAddr())
go handle(conn)
go func() {
for range ticker.C {
if strings.Index(lsofout, regexp.MustCompile(":[0-9]+$").FindAllStringSubmatch(conn.RemoteAddr().String(), -1)[0][0]+" ") > -1 {
golog.Info("close", "Close the connection in %v", conn.RemoteAddr())
conn.Close()
return
}
}
}()
}
}
func handle(conn net.Conn) {
// do something
} |
same problem. by the way, your code have a bug. every time accept will make new go func and only |
@suutaku sorry, I cannot understand that, in which case cause it become a bug? |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
I'm think so
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I want start a TCP server, when I use
telnet
or some client to connect the server, after I close client part, the server part still keep listen port and did not release it(the code did not go to defer function to close Conn).the server log:
The netstat
What did you expect to see?
I want the Conn close when I disconnect it, or close later.
What did you see instead?
always CLOSE_WAIT
The text was updated successfully, but these errors were encountered: