英文:
Why does the client hang when the local port is specified?
问题
这涉及到一个必须用Java提交的作业任务。程序按预期工作,将 server.go 的内容打印到终端。为什么在连续运行两次或更多次之后,客户端会停顿30秒钟?
只有在指定客户端端口时才会出现延迟(与作业相关)。
我期望延迟是等待连接关闭的超时,如果不是因为 defer conn.Close() 和客户端仅在前一个客户端返回后才运行。
在延迟期间的 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
英文:
This is related to a homework assignment that must be submitted in Java. The program works as expected printing the contents of server.go to the terminal. Why does the client hang for 30 seconds after two or more sequential runs?
The delay only occurs when the client port is specified (related to the assignment).
// server.go
package main
import (
"log"
"net/http"
)
func main() {
log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("."))))
}
I'd expect the delay to be a timeout waiting for the connection to close if it were not for defer conn.Close() and the client running only after the previous client returned.
// 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)
}
Output of netstat during a delay:
$ 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
答案1
得分: 0
我可以重现那个错误。据我所知,这与TCP关闭序列有关,可以参考这个链接 - http://www.tcpipguide.com/free/t_TCPConnectionTermination-4.htm
在OS X上,你可以像这样修改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,
},
}
// 从客户端端口8081拨号到服务器端口8080
conn, err := d.Dial("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
// 请求资源并记录响应
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("尝试次数 %d\n", count)
count++
check()
time.Sleep(200 * time.Millisecond)
}
}
参考链接:https://en.wikipedia.org/wiki/Maximum_segment_lifetime
英文:
I can reproduce that error. AFAICS it has to do with the TCP closing sequence, see this - http://www.tcpipguide.com/free/t_TCPConnectionTermination-4.htm
On OS X you can mess with the tcp MSL like this
sudo sysctl net.inet.tcp.msl=100
So a modified client
// 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)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论