socket编程小问题:地址已经被使用——Address already in use

本文探讨了在socket编程中遇到的Address already in use错误,并提供了通过设置SO_REUSEADDR选项来解决该问题的方法。

很多socket编程的初学者可能会遇到这样的问题:如果先ctrl+c结束服务器端程序的话,再次启动服务器就会出现Address already in use这个错误,或者你的程序在正常关闭服务器端socket后还是有这个问题。正如下面的这段简单的socket程序。

 

server.c

 

client.c

 

      在成功的运行了第一次之后,当你再次启动服务器端程序时,./server就变得邪恶起来,在bind()这个函数中居然出现了Address already in use这个错误。

                                 

      然后你开始迷惑了,难道是忘记将socket给关闭了,或是关闭socket的顺序不对?经过种种猜测与试验,你发现问题毫无进展......过了一会,当你再次抱着试试看的态度重新在linux的“黑色终端”中输入./server时,程序居然运行了,什么情况?究其原因,是socket选项在捣鬼。下面是IBM官网上对这一情况的具体解释,参见http://www.ibm.com/developerworks/cn/linux/l-sockpit/

      bind 普遍遭遇的问题是试图绑定一个已经在使用的端口。该陷阱是也许没有活动的套接字存在,但仍然禁止绑定端口(bind 返回 EADDRINUSE),它由 TCP 套接字状态 TIME_WAIT 引起。该状态在套接字关闭后约保留 2 到 4 分钟。在 TIME_WAIT 状态退出之后,套接字被删除,该地址才能被重新绑定而不出问题。

等待 TIME_WAIT 结束可能是令人恼火的一件事,特别是如果您正在开发一个套接字服务器,就需要停止服务器来做一些改动,然后重启。幸运的是,有方法可以避开 TIME_WAIT 状态。可以给套接字应用 SO_REUSEADDR 套接字选项,以便端口可以马上重用。

考虑清单 3 的例子。在绑定地址之前,我以 SO_REUSEADDR 选项调用 setsockopt。为了允许地址重用,我设置整型参数(on)为 1 (不然,可以设为 0 来禁止地址重用)。

      按照IBM的做法,我重新改写了server.c的代码。

server.c

 

       这次,让我们再次反复的启动服务器,尽情的在“黑窗户”里面输入./server ./server ./server ......服务器的程序好像突然间变乖了,呵呵,童鞋们,为自己的成就庆祝吧!!!

### Redis Sentinel 启动时端口 26379 无法绑定的解决方案 Redis Sentinel 启动失败并提示 `Failed listening on port 26379 (TCP)`,通常是因为指定的端口已被其他进程占用。可以通过以下方法排查并解决此问题: 1. **检查端口占用情况** 使用 `netstat` 或 `ss` 命令检查 26379 端口是否被占用。例如: ```bash netstat -tulnp | grep 26379 ``` 或 ```bash ss -tulnp | grep 26379 ``` 如果发现有其他进程正在使用该端口,可以终止该进程或更改 Redis Sentinel 的端口配置[^1]。 2. **终止占用端口的进程** 如果确认该端口确实被其他 Redis Sentinel 实例占用,可以使用 `kill` 命令终止该进程。例如: ```bash kill -9 <PID> ``` 其中 `<PID>` 是占用 26379 端口的进程 ID。此方法适用于需要清理旧的 Sentinel 实例并重新启动新实例的情况[^2]。 3. **更改 Redis Sentinel 的监听端口** 如果不希望终止现有进程,也可以通过修改 Redis Sentinel 配置文件中的 `port` 参数来更改监听端口。例如: ```properties port 26380 ``` 修改后保存配置文件,并重新启动 Redis Sentinel 服务。这样可以避免端口冲突,并确保 Sentinel 正常运行[^1]。 4. **确保配置文件一致性** 在多节点环境中,确保所有 Sentinel 节点的配置文件中 `sentinel announce-ip` 和 `sentinel announce-port` 配置项与实际使用的 IP 和端口一致,以避免因配置不一致导致的连接问题。例如: ```bash echo "sentinel announce-ip 192.168.1.100" >> /etc/redis/sentinel.conf echo "sentinel announce-port 26380" >> /etc/redis/sentinel.conf ``` 这样可以确保 Sentinel 节点在集群中正确广播自己的地址和端口[^5]。 --- ###
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值