dongpan1416 2015-06-20 09:52
浏览 197

Golang关闭网络监听器

I am having trouble closing a listener so that I can reopen it on the same port. I am writing a proxy server that is hot-configurable - i.e what it does (redirects/blocks etc) can be adjusted on the fly. The proxy runs in a go routine. The problem I am having is when I reconfigure the listener and proxy the listener is still using that port from the previous configuration. (FYI listener is a global pointer) I'm trying something like:

to kill the listener:

func KillProxy() {

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

before reconfiguring it like:

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)

however that doesnt seem to work - I get the error:

listener (S1):

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

listener (S2): 0xc2080015e0

and then a massive stack trace that summizes to:

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

EDIT IN RESPONSE TO JIM:

Interesting re pointers. OK. I am not handling waiting for the socket to close, Im not sure how that should be done. The proxy library I am using is this one: https://github.com/abourget/goproxy. The order things happen is:

KillProxy()
refreshProxy()

refreshProxy holds the code posted above that tries to repurpose the listener. The last thing that happens in refreshProxy() is:

go http.Serve(*listener, proxy)

So if I revert to listener being a global variable, not a pointer I can make KillProxy():

func KillProxy() {
    if listener != nil {
        listener.Close()
        listener = nil
    }
}

and then setup the listener again as

listener, err := net.Listen(CONN_TYPE, CONN_HOST + ":" + CONN_PORT) 
    if err != nil {
        log.Println("error here: ", err)
    }    

However I don't know how to wait and check whether the socket has closed before trying to re create the listener object?

  • 写回答

1条回答 默认 最新

  • doupinwan0563 2015-06-21 10:39
    关注

    Ok this is far from perfect, but the only way I found of not having it error out on me was to artifically put a delay in my code so the socket had time to close. This isn't great as it means the proxy is down for 2 seconds while the socket closes, but at least it doesnt error out. If someone has a better solution I would like to hear it

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

报告相同问题?

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看