2015-06-20 186 views
2

我在关闭监听器时遇到问题,因此我可以在同一个端口上重新打开监听器。我正在编写一个热配置的代理服务器,即它可以随时调整(重定向/阻止等)。代理运行在去程序中。我遇到的问题是,当我重新配置侦听器并且代理侦听器仍然使用以前配置中的那个端口时。 (仅供参考监听器是一个全球性的指针) 我想是这样的:Golang关闭网络监听器

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) 

然而,这并不似乎工作:重新配置它像以前一样

func KillProxy() { 

    if listener != nil { 
     log.Println(" *** TRYING TO STOP THE PROXY SERVER") 
     (*listener).Close() 
     listener = nil 
    } 
} 

杀监听器 - 我得到的错误:

listener (S1):

error here: listen tcp 0.0.0.0:8080: bind: address already in use

listener (S2): 0xc2080015e0

然后一个大规模的堆栈跟踪s ummizes到:

panic: runtime error: invalid memory address or nil pointer dereference

编辑回应JIM:

有趣重新指针。好。我没有处理等待socket关闭,我不知道应该怎么做。我使用的代理库是这样的: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) 
    }  

但是我不知道如何等待并检查套接字是否已关闭,然后尝试重新创建lis tener对象?

+1

切勿使用指针的接口,这只是混乱的问题,可能与您的恐慌。如果端口被绑定,那么在再次绑定之前,您并未等待套接字关闭。请显示实际的代码处理。 – JimB

+0

如果错误!= nil',我认为你不应该使用'l'。我不记得公约是什么,但我可以想象它只是垃圾。 – ReyCharles

+0

@JimB我编辑了我原来的帖子。 – amlwwalker

回答

-1

好吧,这是远远不够完美的,但我发现没有错误的唯一方法是在我的代码中人工延迟,所以套接字有时间关闭。 这并不好,因为它意味着代理在套接字关闭时关闭了2秒,但至少它没有出错。 如果有人有更好的解决办法,我想听听它

func KillProxy() { 
    if listener != nil { 
     listener.Close() 
     log.Println("waiting for socket to close") 
     time.Sleep(2 * time.Second) 
    } 
} 
+0

使用睡眠是协调并发的最糟糕的方式,尤其是因为仍然不能保证它不会惊慌。你需要等待http.Serve返回,然后启动一个新的监听器。 – JimB

+0

是的,我已经解决这个问题,现在没有延误。我现在有一个包裹一个侦听器并处理自己关闭的结构。花了一段时间来破解,但到最后 – amlwwalker