Go 当指定本地端口时,为什么客户端挂起?
这与必须用Java提交的家庭作业有关。程序按预期工作,打印服务器的内容。转到终端。为什么客户端在两次或多次连续运行后挂起30秒 延迟仅在指定客户端端口时发生(与分配相关) 如果不是因为defer conn.close()和只有在前一个客户端返回后才运行的客户端,我希望延迟是等待连接关闭的超时Go 当指定本地端口时,为什么客户端挂起?,go,ports,Go,Ports,这与必须用Java提交的家庭作业有关。程序按预期工作,打印服务器的内容。转到终端。为什么客户端在两次或多次连续运行后挂起30秒 延迟仅在指定客户端端口时发生(与分配相关) 如果不是因为defer conn.close()和只有在前一个客户端返回后才运行的客户端,我希望延迟是等待连接关闭的超时 // client.go package main import ( "fmt" "io" "log" "net" "os" ) func main() {
// client.go
package main
import (
"fmt"
"io"
"log"
"net"
"os"
)
func main() {
d := net.Dialer{
LocalAddr: &net.TCPAddr{
Port: 8081,
},
}
// Dial the server from client port 8081 to server port 8080
conn, err := d.Dial("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
// Request the resource and log the response
fmt.Fprint(conn, "GET /server.go HTTP/1.0\r\n\r\n")
io.Copy(os.Stdout, conn)
}
延迟期间netstat的输出:
$ netstat -anp tcp | grep "8080\|8081"
tcp4 0 0 127.0.0.1.8081 127.0.0.1.8080 SYN_SENT
tcp46 0 0 *.8080 *.* LISTEN
我可以重现那个错误。AFAICS它与TCP关闭顺序有关,请参见此- 在OSX上,您可以像这样处理tcp MSL
sudo sysctl net.inet.tcp.msl=100
因此,一个经过修改的客户机
// client.go
package main
import (
"fmt"
"io"
"log"
"net"
"os"
"time"
)
func check() {
d := net.Dialer{
LocalAddr: &net.TCPAddr{
Port: 8081,
},
}
// Dial the server from client port 8081 to server port 8080
conn, err := d.Dial("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
// Request the resource and log the response
fmt.Fprint(conn, "GET /server.go HTTP/1.0\r\n\r\n")
io.Copy(os.Stdout, conn)
conn.Close()
}
// sudo sysctl net.inet.tcp.msl=100
func main() {
count := 0
for {
fmt.Printf("Try num %d\n", count)
count++
check()
time.Sleep(200 * time.Millisecond)
}
}
请参阅,可能是因为端口8081在连接关闭后仍处于等待状态。我已经试着运行你的程序,我没有任何问题,我可以按顺序运行。谢谢@siritinga。如果是这样的话,我不知道为什么netstat说它处于SYN_SENT状态,以及为什么没有为所有请求触发延迟,但它可能会导致某些情况。我也不知道。我的计算机(Ubuntu 14.04)没有问题,可能默认的TCP堆栈配置不同。无法在我的系统(go1.4 windows/amd64)上重现问题。
// client.go
package main
import (
"fmt"
"io"
"log"
"net"
"os"
"time"
)
func check() {
d := net.Dialer{
LocalAddr: &net.TCPAddr{
Port: 8081,
},
}
// Dial the server from client port 8081 to server port 8080
conn, err := d.Dial("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
// Request the resource and log the response
fmt.Fprint(conn, "GET /server.go HTTP/1.0\r\n\r\n")
io.Copy(os.Stdout, conn)
conn.Close()
}
// sudo sysctl net.inet.tcp.msl=100
func main() {
count := 0
for {
fmt.Printf("Try num %d\n", count)
count++
check()
time.Sleep(200 * time.Millisecond)
}
}