首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

关于socket的SO_REUSEADDR在golang中不能很好地工作吗?

SO_REUSEADDR是一个socket选项,用于允许在同一端口上快速重用处于TIME_WAIT状态的socket。在golang中,SO_REUSEADDR选项是默认启用的,因此可以很好地工作。

SO_REUSEADDR的作用是允许一个socket绑定到一个已经被使用的地址,只要该地址处于TIME_WAIT状态。这在服务器程序中特别有用,因为服务器程序经常需要在关闭后立即重新启动。通过设置SO_REUSEADDR选项,服务器程序可以立即重新绑定到相同的地址和端口,而无需等待TIME_WAIT状态的socket完全释放。

在golang中,可以通过设置net包中的ListenConfig结构体的属性来启用SO_REUSEADDR选项。具体代码如下:

代码语言:txt
复制
package main

import (
    "fmt"
    "net"
)

func main() {
    lc := net.ListenConfig{
        Control: func(network, address string, c syscall.RawConn) error {
            return c.Control(func(fd uintptr) {
                syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
            })
        },
    }

    ln, err := lc.Listen(context.Background(), "tcp", ":8080")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    // 后续处理逻辑...
}

在上述代码中,通过设置ListenConfig的Control属性,可以在创建监听器时设置SO_REUSEADDR选项。这样,即使之前的socket处于TIME_WAIT状态,也可以立即重新绑定到相同的地址和端口。

总结:在golang中,SO_REUSEADDR选项是默认启用的,可以很好地工作。通过设置net包中的ListenConfig结构体的属性,可以在创建监听器时启用SO_REUSEADDR选项。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

告知你不为人知的 UDP:连接性和负载均衡

引言 作为文章”《从TCP三次握手说起 : 浅析TCP协议中的疑难杂症》”的姊妹篇,很早就计划写篇关于UDP的文章,尽管UDP协议远没TCP协议那么庞大、复杂,但是,要想将UDP描述清楚,用好UDP却要比...然而对于UDP却无法很好的采用PMP机制,由于UDP的无连接性、无序性,它没有通信对端的信息,不知道一个数据包的前置和后续,它没有很好的办法知道,还有没后续的数据包以及如果有的话,过多久才会来,会来多久...会接收到数据,其它的都是默默地等待,孤独地等待永远也收不到UDP数据。...于是基本的解决方案是在整个服务过程中不能关闭UDP socket(当然也可以全部UDP socket都close掉,从新创建一批新的)。...由于内核查找算法是固定的,于是,无形中所有的client被划分为8类,类型1的所有client请求全部被路由到工作进程1的UDP socket由工作进程1来处理,同样类型2的client的请求也全部被工作进程

16.4K143

套接字中SO_REUSEPORT和SO_REUSEADDR的区别

其另一作用也是为什么大家在进行服务器端编程的时候会采用SO_REUSEADDR选项的原因。为了理解其另一个作用及其重要应用,我们需要先更深入地讨论一下TCP协议的工作原理。...因为优雅地关闭TCP socket是一个比较复杂的过程,过程中包括与远程主机交换数个数据包(包括在丢包的情况下的丢失重传),而这个数据包交换的过程所需要的时间也包括在延迟时间中。...但需要注意的是,在某些时候,将一个新的socket绑定在一个处于TIME_WAIT阶段但仍在工作的socket所对应的地址端口对会产生一些我们并不想要的,无法预料的负面影响。...最后,关于SO_REUSEADDR,我们还要注意的一件事是,以上所有内容只要我们对新的socket设置了SO_REUSEADDR就成立。...在Windows中对一个socket设置SO_REUSEADDR的效果与在BSD下同时对一个socket设置SO_REUSEPORT和SO_REUSEADDR相同。

3.6K21
  • 记time_wait状态引起的端口占用排查

    问题背景 在Liunx服务器上发现有 10倍于 LISTEN 服务的 time_wait 状态,服务并非高并发,日常的连接数也比较少,因此该现象明显异常 1....问题定位 time_wait状态 回顾下 time_wait 状态处于 TCP 通信的哪个阶段: 在TCP四次挥手过程中,主动断开连接的一方会在发送完最后一个 ACK 包后,等待 2MSL(Maximum...-52000 sysctl -p SO_REUSEADDR和SO_REUSEPORT 关于这两个参数的概念理解并不是本篇的重点,大家可以参考SO_REUSEADDR和SO_REUSEPORT作用这篇博文的解释..."golang.org/x/sys/unix" ) if fd, err := syscall.Socket(syscall.AF_INET, syscall.O_NONBLOCK|syscall.SOCK_STREAM...,下一篇会总结当服务端口频繁被其他随机分配端口占用的情况下,可以如何通过 Golang或其他代码来解决

    1.4K40

    Golang预绑定端口规避端口抢占问题

    背景介绍 接上篇文章 记time_wait状态引起的端口占用排查 介绍的排查 time_wait 的方法,并不能从根本上解决客户端随机分配的端口抢占本应分配给服务器的端口的问题 1....方案描述 一般在服务器上都存在一些需要预留的端口,除了上篇介绍的 net.ipv4.ip_local_port_range参数以外,没有很好的预留非连续端口的方式,只能提前绑定需要的端口 如果直接绑定或监听需要预分配的端口的话...,当真正需要使用该端口时,还需要经历释放端口、重新绑定,并且还可能出现 Address is in use 的问题 解决方案是利用 SO_REUSEADDR和SO_REUSEPORT 参数的特性,在预绑定时设置这两个参数...*net.IPNet); ok { return n.IP.String(), nil } } } } } return "", nil } 绑定端口 Golang...中包含 syscall包,可以调用系统函数。

    1.4K30

    提高服务端性能的几个socket选项

    提高服务端性能的几个socket选项 在之前的一篇文章中,作者在配置了SO_REUSEPORT选项之后,使得应用的性能提高了数十倍。...现在介绍socket选项中如下几个可以提升服务端性能的选项: SO_REUSEADDR SO_REUSEPORT SO_ATTACH_REUSEPORT_CBPF/EBPF 验证环境:OS:centos...如果一个socket绑定到了0.0.0.0:21,则表示该socket绑定了所有现有的本地地址,此时,其他socket不能绑定到任何本地地址的21端口上。...启用SO_REUSEADDR 选项后,在例1中的bind前添加如下代码,然后运行,此时不会再报错: int optval = 1; setsockopt(lfd, SOL_SOCKET,...在提高UDP交互性能一文中,提高流量的一个方式就是使用BPF程序将socket与CPU核关联起来,实际就是将一个socket与这个核上的流进行了关联,防止因为哈希算法导致多条流争用同一个socket导致性能下降

    1.5K20

    字节一面:TCP 和 UDP 可以使用同一个端口吗?

    关于端口的知识点,还是挺多可以讲的,比如还可以牵扯到这几个问题: 多个 TCP 服务进程可以同时绑定同一个端口吗? 客户端的端口可以重复使用吗?...我们可以在调用 bind 前,对 socket 设置 SO_REUSEADDR 属性,可以解决这个问题。...如果 TCP 服务进程对 socket 设置 SO_REUSEADDR 属性了,那么在重启时,即使存在一个和绑定 IP+PORT 一样的 TIME_WAIT 状态的连接,依然可以正常绑定成功,因此可以正常重启成功...因此,在所有 TCP 服务器程序中,调用 bind 之前最好对 socket 设置 SO_REUSEADDR 属性,这不会产生危害,相反,它会帮助我们在很快时间内重启服务端程序。‍...要解决这个问题,我们可以对 socket 设置 SO_REUSEADDR 属性。

    1.7K21

    通过Node.js的Cluster模块源码,深入PM2原理

    Node.js无疑是走向大前端、全栈工程师技术栈最快的捷径(但是一定要会一门其他后台语言,推荐Golang),虽然Node.js做很多事情都做不好,但是在某些方面还是有它的优势。...我在Node.js的官网找到了答案: image.png 原来所有的net.Socket都被设置了SO_REUSEADDR 这个SO_REUSEADDR到底是什么呢?...) 单进程或线程创建socket,并进行listen,预先创建好多个工作进程或线程accept()在同一个服务器套接字 这两种模型解充分发挥了多核CPU的优势,虽然可以做到线程和CPU核绑定,但都会存在...上面有提到SO_REUSEADDR选项,在主进程调用的_listen2中就有设置。 子进程初始化的每个workerinit函数中,也有cluster....2.在内部TCP服务器的请求处理逻辑中,有负载均衡地挑选出一个worker进程,将其发送一个newconn内部消息,随消息发送客户端句柄。

    3K30

    socket的SO_REUSEADDR参数全面分析

    当处于listen状态的socket监听的本地地址的ip部分是INADDR_ANY,即表示监听本地的所有ip,即使使用这个参数,也不能再bind包含这个端口的任意本地地址,这个和 2 中描述的其实是一样的...其实,这个在最开始的man文档中已经说过了,只要有listen占了一个本地地址,其他任何操作都不能再使用这个地址了。...在我们的新socket和sk2本地地址相同时,如果新socket没有设置SO_REUSEADDR参数,或者sk2没设置SO_REUSEADDR参数,或者sk2为listen状态,sk2最终都会不为null...和man文档中说的基本是一样的。 那我们在平时写服务器时,为什么要加上这个参数呢?...我们知道,在tcp连接中,主动发起关闭请求的那一端会最终进入TIME_WAIT状态,被动关闭连接的那一端会直接进入CLOSE状态,即socket和它占用的资源会直接销毁。

    2.9K21

    问题:Springboot框架开发的项目中会内嵌tomcat容器,在杀死进程的时候tomcat为被正常杀死,导致端口未被释放,第二次启动的时候报端口冲突。

    kill -9 pid则是向进程号为pid的进程发送SIGKILL(该信号的编号为9),从本文上面的说明可知,SIGKILL既不能被应用程序捕获,也不能被阻塞或忽略,其动作是立即结束指定进程。...通俗地说,应用程序根本无法“感知”SIGKILL信号,它在完全无准备的情况下,就被收到SIGKILL信号的操作系统给干掉了,显然,在这种“暴力”情况下,应用程序完全没有释放当前占用资源的机会。...事实上,SIGKILL信号是直接发给init进程的,它收到该信号后,负责终止pid指定的进程。关于linux init进程的说明,可以参考这里或这里。...所以我们在这里调整stop之后休眠10s在启动start 还有一种情况是:setsockopt中参数SO_REUSEADDR 一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR...SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用。server程序总是应该在调用bind()之前设置SO_REUSEADDR套接字选项。

    67220

    经典面试题(三)之网络通信题目集锦

    TCP与UDP的区别与适用场景 5. linux常见网络模型详解(select、poll与epoll) 6. epoll_event结构中的epoll_data_t的fd与ptr的使用场景 7....异步的connect函数如何编写 10.select函数可以检测网络异常吗? 11. epoll的水平模式和边缘模式 12....如何将socket设置成非阻塞的(创建时设置与创建完成后设置),非阻塞socket与阻塞的socket在收发数据上的区别 13. send/recv(read/write)返回值大于0、等于0、小于0的区别...18.socket选项SO_REUSEADDR和SO_REUSEPORT(Windows平台与linux平台的区别) 19.socket选项SO_LINGER 20.shutdown与优雅关闭 21....socket选项SO_KEEPALIVE 22.关于错误码EINTR 23.如何解决tcp粘包问题 24.信号SIGPIPE与EPIPE错误码 25.gethostbyname阻塞与错误码获取问题 26

    2.6K30

    PHP网络编程之深入Libevent(十五节)

    毫不要脸地说,我写的这些文章都不属于快餐消耗品,你不动手亲自实践是压根搞不定的,哪儿有那么容易就能得到的认知啊!况且我讲的并不全,有很多资料知识是需要你自己搜索补充的。...我再次强调一遍:这种xue微偏底层一丢丢的基础知识,绝非类似于《XXX框架实战小程序》、《YYY框架实战电商》,这种基础知识看了后不会有立竿见影的效果,甚至你在工作里CURD都用不到。...其实这事儿看起来应该挺简单的,好像大概似乎按葫芦画瓢就能搞定,但,是么?来来,琢磨一下,什么时候向客户端写入数据,是在Event::READ事件的回调函数中吗?...这么做听起来是顺理成章的,在回调中读取了客户端飞过来的数据后,马上使用socket_write()等把数据再飞回去给客户端... MD,那还要Event::WRITE有何用?...一般说来一个完整常规的写事件的使用方法是:当Event::READ事件发生后,在回调函数中首先读取数据,然后准备一个发送数据的自定义缓冲区,当这个发送数据的自定义缓冲区(注意不是socket缓冲区)中没有数据后

    1K31

    (二)Reactor模式

    其实,SO_REUSEADDR在windows上和Unix平台上还有些细微的区别,我在libevent源码中看到这样的描述: int evutil_make_listen_socket_reuseable...也就是在在Unix平台上,如果不设置这个选项,任意进程在一定时间内,不能bind该地址;在windows平台上,在一定时间内,其他进程不能bind该地址,而本进程却可以再次bind该地址。...因为如果采取水平触发模式的话,主线程检测到某个客户端socket数据可读时,通知工作线程去收取该socket上的数据,这个时候主线程继续循环,只要在工作线程没有将该socket上数据全部收完,或者在工作线程收取数据的过程中...相反,采取边缘触发模式,只有等某个工作线程将那个客户端socket上数据全部收取完毕,主线程的epoll_wait才可能会再次触发来通知工作线程继续收取那个客户端socket新来的数据。 5....代码中有这样一行: //gdb调试时不能实时刷新标准输出,用这个函数刷新标准输出,使信息在屏幕上实时显示出来 std::cout << std::endl; 如果不加上这一行,正常运行服务器程序,程序中要打印到控制台的信息都会打印出来

    1.7K80

    socket的五大误区

    send API 函数有三类可能的返回值: 如果数据成功地排到传输队列,则返回 0。 如果排队失败,则返回 -1(通过使用 errno 变量可以了解失败的原因)。...可以给套接字应用 SO_REUSEADDR 套接字选项,以便端口可以马上重用。 考虑清单 3 的例子。在绑定地址之前,我以 SO_REUSEADDR 选项调用 setsockopt。...( sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ); /* Allow connections to port 8080 from any available...但是如果试图在一个套接字上发送二进制数据,事情将会变得更加复杂。 比如说,您想要发送一个整数:您可以肯定,接收者将使用同样的方式来解释该整数吗?...GNU/Linux 工具和实用程序还可以帮助发现一些程序中的小问题。记住:在查看实用程序的帮助手册时候,跟踪相关的或“请参见”工具。您也许会发现一个必要的新工具。

    82620

    linux udp编程_linux中socket编程

    但是,并不是说我们就不能主动的进行bind的操作。...3、关于服务端的bind操作,在存在组播,多播等多种通信方式的情况下,也还有一些需要注意的点,这个我们在下面的章节中描述 二、UDP通信的基本函数说明 在UDP中,完成一个基本的通信涉及到的几个函数如下...addrlen参数很好理解,就是struct sockaddr参数的长度,一般在使用的过程中也不会有什么疑问,但是我们在使用recvfrom时,就需要注意addrlen这个参数了,如果我们不需要关心发送者的...解决方法如下:(允许端口重用) int on = 1; ret = setsockopt(udp_net_sta.socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof...(int)); if (ret < 0) { perror("socket set SO_REUSEADDR failed"); } 2、服务端程序,在创建完socket后,有一个bind的操作

    11.1K10

    Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程

    SO_REUSEADDR选项 在上一篇文章的最后我们贴出了一个简单的C/S通信的例程。...在该例程序中,使用"Ctrl+c"结束通信后,服务器是无法立即重启的,如果尝试重启服务器,将被告知: bind: Address already in use 原因在于服务器重新启动时需要绑定地址...服务器端尽可能使用REUSEADD,在bind()之前调用setsockopt来设置SO_REUSEADDR套接字选项,使用SO_REUSEADDR选项可以使不必等待TIME_WAIT状态消失就可以重启服务器...ERR_EXIT("setsockopt error"); 处理多客户的服务器 在上一篇文章例程中,服务器端只能够连接一个客户端,并不能处理多个客户端的连接。...当一个新的客户端连接已经放入已连接队列时,服务器并不能执行到accpet的代码去获取队列中的连接。

    62130

    【Linux】:传输层协议 UDP

    一、前言 之前在这篇文章 初识网络 中说过关于传输层的内容,以及在 Socket编程应用层UDP 也做过关于 UDP 的练习,如下: 传输层: 负责两台主机之间的数据传输。...但是值得注意的是:在特定情况下是可以的 使用 SO_REUSEADDR 选项: 通过设置套接字选项 SO_REUSEADDR,多个进程可以绑定到同一个端口号。...解包:UDP 直接读取报文前 8 个字节(16 位源端口号)来进行解包 分用: UDP 根据16位端口号去 OS 中查找进程与这16位端口号关联的 从这就可以知道我们在 Socket编程应用层UDP...文章这 UDP的端口号只有两字节,因为 OS 在协议中规定端口号是 16 位的,因此我们当时 ip 地址是 4 字节,而 端口号却是 2 字节,这就是 协议源代码 这里 UDP 携带16 位 UDP 长度...但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致; 如果缓冲区满了, 再到达的 UDP 数据就会被丢弃; UDP 的 socket 既能读, 也能写, 这个概念叫做 全双工

    12210

    Python入门之并发编程IO模型

    #举例: #1. multiprocessing.Pool下的apply #发起同步调用后,就在原地等着任务结束, #根本不考虑任务是在计算还是在io阻塞,总之就是一股脑地等任务结束 #2. concurrent.futures.ProcessPoolExecutor...阻塞调用:当socket工作在阻塞模式的时候,如果没有数据的情况下调用recv函数, #则当前线程就会被挂起,直到有数据为止。...这两种技术#都可以很好的降低系统开销,都被广泛应用很多大型系统,如websphere、tomcat和各种数#据库等。...对应上例中的所面临的可能同时出现的上千甚至上万次的客户端请求,“线程池”或“连接池”或许可以缓解部分压力,但是不能解决所有问题。...在多路复用模型中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。

    59770

    (二)Reactor模式

    其实,SO_REUSEADDR在windows上和Unix平台上还有些细微的区别,我在libevent源码中看到这样的描述: 1int evutil_make_listen_socket_reuseable...也就是在在Unix平台上,如果不设置这个选项,任意进程在一定时间内,不能bind该地址;在windows平台上,在一定时间内,其他进程不能bind该地址,而本进程却可以再次bind该地址。...因为如果采取水平触发模式的话,主线程检测到某个客户端socket数据可读时,通知工作线程去收取该socket上的数据,这个时候主线程继续循环,只要在工作线程没有将该socket上数据全部收完,或者在工作线程收取数据的过程中...相反,采取边缘触发模式,只有等某个工作线程将那个客户端socket上数据全部收取完毕,主线程的epoll_wait才可能会再次触发来通知工作线程继续收取那个客户端socket新来的数据。...代码中有这样一行: //gdb调试时不能实时刷新标准输出,用这个函数刷新标准输出,使信息在屏幕上实时显示出来 std::cout << std::endl; 如果不加上这一行,正常运行服务器程序,程序中要打印到控制台的信息都会打印出来

    1.1K60
    领券