英文:
Why does net.Conn.close() seem to be closing at the wrong time?
问题
我正在尝试从TCP客户端读取和写入一些命令。我希望在最后一个函数执行完毕后关闭连接,但由于某种原因,即使明确放置在函数之后,似乎服务器在函数执行过程中断开了连接。
package main
import (
"bufio"
"fmt"
"io"
"log"
"net"
"strconv"
"strings"
"time"
)
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
}
go handleConn(conn)
conn.Close()
}
}
func handleConn(someconnection net.Conn) {
func1(someconnection)
func2(someconnection) //在执行此部分时连接中断
}
func func2(someconnection net.Conn) {
//发送消息(字符串)
_, err := io.WriteString(someconnection, dosomething)
if err != nil {
log.Fatal(err)
}
//等待回复
//发送另一条消息
_, err = io.WriteString(someconnection, dosomething)
if err != nil {
log.Fatal(err)
}
//等待回复
//发送另一条消息,连接往往在这里关闭
_, err = io.WriteString(someconnection, dosomething)
if err != nil {
log.Fatal(err)
}
//等待,发送
_, err = io.WriteString(someconnection, dosomething)
if err != nil {
log.Fatal(err)
}
//等待,读取并打印消息
c := bufio.NewReader(someconnection)
buff1 := make([]byte, maxclientmessagelength)
buff1, err = c.ReadBytes(delimiter)
fmt.Printf("\n%s\n", buff1)
_, err = io.WriteString(someconnection, dosomething)
if err != nil {
log.Fatal(err)
}
}
这意味着试图进行反向通信的客户端无法进行通信,但程序会一直运行到结束。
更新1:
通过将延迟关闭语句放置在获取连接时,取得了一些进展。
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
}
defer conn.Close()
go handleConn(conn)
}
}
现在它不一定会在我希望关闭的那一秒内关闭,但至少现在它可以完整运行到结束。
英文:
I'm trying to read and write some commands from a TCP client. I want to close a connection after the last function has been executed but for some reason, it seems like the server disconnects the connection in the middle of the function even when explicitly placed afterward.
package main
import (
"bufio"
"fmt"
"io"
"log"
"net"
"strconv"
"strings"
"time"
)
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
}
go handleConn(conn)
conn.Close()
}
}
func handleConn(someconnection net.Conn) {
func1(someconnection)
func2(someconnection) //connection drops in the middle of executing this part
}
func func2(someconnection net.Conn) {
//send message(a string)
_, err := io.WriteString(someconnection, dosomething)
if err != nil {
log.Fatal(err)
}
//await reply
//send another message
_, err = io.WriteString(someconnection, dosomething)
if err != nil {
log.Fatal(err)
}
//await reply
//send another message, connection tends to close somewhere here
_, err = io.WriteString(someconnection, dosomething)
if err != nil {
log.Fatal(err)
}
//await,send
_, err = io.WriteString(someconnection, do something)
if err != nil {
log.Fatal(err)
}
//await, read and print message
c := bufio.NewReader(someconnection)
buff1 := make([]byte, maxclientmessagelength)
buff1, err = c.ReadBytes(delimiter)
fmt.Printf("\n%s\n", buff1)
_, err = io.WriteString(someconnection, dosomething)
if err != nil {
log.Fatal(err)
}
}
That means the client trying to communicate backward simply isn't able to communicate but the program runs to the end.
Update 1:
Made some progress by placing the deferred close statement to when the connection was first acquired.
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
}
defer conn.Close()
go handleConn(conn)
}}
Now it doesn't necessarily close within the second I hope it to close but at least it now runs all the way through.
答案1
得分: 2
Goroutines是异步的,所以在这里调用handleConn之后:
go handleConn(conn)
conn.Close()
主函数会继续执行并关闭连接。
尝试正常调用handleConn函数(不使用go
)。
英文:
Goroutines are asynchronous so after calling handleConn here:
go handleConn(conn)
conn.Close()
the main function continues to execute and closes the connection.
Try just calling the handleConn function regularly (without the go
).
答案2
得分: 1
conn.Close
需要在 handleConn
完成其工作之后执行。你可以使用通道将其传递回主线程,但这会过于复杂(还会阻塞主线程的执行)。以下是正确的做法:
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
}
go handleConn(conn)
// 移除下面这行代码
// conn.Close()
}
}
在 handleConn
函数内部添加 conn.Close
:
func handleConn(someconnection net.Conn) {
// 在下面添加这行代码
defer someconnection.Close()
func1(someconnection)
func2(someconnection)
}
这样可以确保在 func1
和 func2
执行完毕后再调用 conn.Close
。
英文:
The conn.Close
needs to de done AFTER handleConn
has done its work. You could communicate the back to the main thread using channels but that would be too complex (and also block execution of main thread). This is how it should be done
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
}
go handleConn(conn)
// REMOVE BELOW LINE
// conn.Close()
}
}
Add conn.Close
inside handleConn
func handleConn(someconnection net.Conn) {
// ADD BELOW LINE
defer someconnection.Close()
func1(someconnection)
func2(someconnection)
}
This makes sure conn.Close
is called AFTER func1
and func2
are done executing
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论