当前位置: 首页 > 面试题库 >

如何使用Go编程语言可靠地unlink()Unix域套接字

施飞鸿
2023-03-14
问题内容

我有一个Go程序,在其上托管了一个简单的HTTP服务,localhost:8080因此我可以nginx通过该proxy_pass指令将我的公共主机连接到它,作为反向代理来满足我的网站请求的一部分。一切都很好,在那里没有问题。

我想将Go程序转换为在Unix域套接字而不是本地TCP套接字上承载HTTP服务,以提高安全性并减少TCP不必要的协议开销。

问题
:问题在于bind(),即使程序终止后,Unix域套接字也无法重用。第二次(以及之后的每一次)我运行Go程序时,都会退出并出现致命错误"address already in use"

通常的做法是unlink()在服务器关闭时使用Unix域套接字(即删除文件)。但是,这在Go中很棘手。我的第一次尝试是defer在主函数中使用该语句(请参见下文),但是如果我使用CTRL-
C之类的信号中断该进程,该语句将不会运行。我想这是可以预料的。令人失望,但并非意外。

问题unlink()在服务器进程关闭(优雅地或非优雅地)时如何建立套接字的最佳实践?

这是我的一部分,func main()它启动服务器以供参考:

// Create the HTTP server listening on the requested socket:
l, err := net.Listen("unix", "/tmp/mysocket")
if err != nil {
    log.Fatal(err)
} else {
    // Unix sockets must be unlink()ed before being reused again.
    // Unfortunately, this defer is not run when a signal is received, e.g. CTRL-C.
    defer func() {
        os.Remove("/tmp/mysocket")
    }()

    log.Fatal(http.Serve(l, http.HandlerFunc(indexHtml)))
}

问题答案:

这是我使用的完整解决方案。我在问题中发布的代码是简化版本,目的是清楚地进行演示。

// Create the socket to listen on:
l, err := net.Listen(socketType, socketAddr)
if err != nil {
    log.Fatal(err)
    return
}

// Unix sockets must be unlink()ed before being reused again.

// Handle common process-killing signals so we can gracefully shut down:
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM)
go func(c chan os.Signal) {
    // Wait for a SIGINT or SIGKILL:
    sig := <-c
    log.Printf("Caught signal %s: shutting down.", sig)
    // Stop listening (and unlink the socket if unix type):
    l.Close()
    // And we're done:
    os.Exit(0)
}(sigc)

// Start the HTTP server:
log.Fatal(http.Serve(l, http.HandlerFunc(indexHtml)))

我肯定希望这是一个好而有效的Go代码,它将使Go作者感到骄傲。在我看来确实如此。如果不是这样,那会让我感到尴尬。:)

对于任何好奇的人来说,这都是https://github.com/JamesDunne/go-index-
html的
一部分,它是一个简单的HTTP目录列表生成器,具有Web服务器无法为您提供的一些额外功能。



 类似资料:
  • 问题内容: 我有以下代码,应使用RTNETLINK套接字监视网络更改。但是,当我为接口“ New Addr”或“ Del Addr”设置新的IP地址时,不会显示。可能是什么问题。 问题答案: 我发现 文件包中了。常量变量 。但是 在 源代码中定义的C语言中的模拟常量具有不同的值,如下所示: 我通过github.com 提交了问题,希望在以后的版本中可以解决。 现在,您可以在插入的代码中使用。它将完

  • 本书涵盖 CGO、Go 汇编语言、RPC 实现、Web 框架实现、分布式系统等高阶主题,针对Go语言有一定经验想深入了解Go语言各种高级用法的开发人员。

  • 本书涵盖CGO、Go汇编语言、RPC实现、Web框架实现、分布式系统等高阶主题,针对Go语言有一定经验想深入了解Go语言各种高级用法的开发人员。对于刚学习Go语言的读者,建议先从《Go语言圣经》开始系统学习Go语言的基础知识。 目录 第一章 语言基础 1.1. Go语言创世纪 1.2. Hello, World 的革命 1.3. 数组、字符串和切片 1.4. 函数、方法和接口 1.5. 面向并发的

  • 作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。 Go 语言中变量可以在三个地方声明: 函数内定义的变量称为局部变量 函数外定义的变量称为全局变量 函数定义中的变量称为形式参数 接下来让我们具体了解局部变量、全局变量和形式参数。 局部变量 在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。 以下实例中 main() 函数使用了局

  • 问题内容: TCP具有元组对(IP地址/端口/类型)来告诉另一个客户端。UDP传递客户端IP和端口。unix域如何跟踪不同的客户端? 换句话说,服务器创建一个绑定到某个路径的套接字,例如/ tmp / socket。2个或更多客户端连接到/ tmp / socket。底层发生了什么,可跟踪来自client1和client2的数据?我想网络堆栈在域套接字中不起作用,所以内核在这里完成所有工作吗? 是

  • 问题内容: 我听到来自Google的关于Go编程语言的嗡嗡声。维基百科是这样描述的:“ Go旨在通过简化动态语言的编程来提供静态类型的编译语言的效率”。我当时在想,由于它是android制造商提供的一种语言,因此他们应该对创建android应用程序有一些支持。有没有可以从Go创建android应用程序的工具?使用“ SOMEDAY” android可能基于GO的假设来学习Go语言是否值得。 问题答