【发布时间】:2015-09-06 06:59:45
【问题描述】:
我无法关闭侦听器,以便在同一端口上重新打开它。我正在编写一个可热配置的代理服务器 - 即它的作用(重定向/阻止等)可以即时调整。代理在 go 例程中运行。我遇到的问题是,当我重新配置侦听器和代理时,侦听器仍在使用先前配置中的该端口。 (仅供参考的监听器是一个全局指针) 我正在尝试类似:
杀死听众:
func KillProxy() {
if listener != nil {
log.Println(" *** TRYING TO STOP THE PROXY SERVER")
(*listener).Close()
listener = nil
}
}
在重新配置之前:
log.Println("listener (S1): ", listener)
if listener == nil {
// Start the listener to listen on the connection.
l, err := net.Listen(CONN_TYPE, CONN_HOST + ":" + CONN_PORT)
if err != nil {
log.Println("error here: ", err)
}
listener = &l //set it as a pointer to the newly created listener
}
log.Println("listener (S2): ", listener)
但这似乎不起作用 - 我收到错误:
监听器(S1):
此处出错:listen tcp 0.0.0.0:8080: bind: address already in use
监听器(S2):0xc2080015e0
然后是一个巨大的堆栈跟踪,总结为:
恐慌:运行时错误:无效的内存地址或 nil 指针取消引用
针对 JIM 进行编辑:
有趣的重新指针。好的。我没有处理等待套接字关闭,我不知道应该怎么做。我使用的代理库是这个:https://github.com/abourget/goproxy。事情发生的顺序是:
KillProxy()
refreshProxy()
refreshProxy 包含上面发布的代码,它试图重新调整侦听器的用途。 refreshProxy() 发生的最后一件事是:
go http.Serve(*listener, proxy)
因此,如果我将侦听器恢复为全局变量,而不是指针,我可以创建 KillProxy():
func KillProxy() {
if listener != nil {
listener.Close()
listener = nil
}
}
然后将监听器再次设置为
listener, err := net.Listen(CONN_TYPE, CONN_HOST + ":" + CONN_PORT)
if err != nil {
log.Println("error here: ", err)
}
但是在尝试重新创建监听器对象之前,我不知道如何等待并检查套接字是否已关闭?
【问题讨论】:
-
永远不要使用指向接口的指针,它只会混淆问题并且可能与您的恐慌有关。如果端口已绑定,那么您无需等待套接字关闭即可再次绑定。请展示实际的代码处理方式。
-
如果
err != nil,我认为你不应该使用l。我不记得约定是什么,但我可以想象它只是垃圾。 -
@JimB 我已经编辑了我的原始帖子。
-
您必须在接受循环周围处理关闭套接字,因此请检查 http.Serve 重新调整的错误。另外,不要将监听器设置为 nil(尝试使用竞赛检测器运行)
-
@JimB 好的,我可以针对 .Serve 进行测试,但如果出现错误,我是否需要延迟或重新调用它? Ok 将删除 KillProxy() 中的
listener = nil。抱歉,种族检测器是什么?你知道这样的例子吗?
标签: go proxy listener goroutine