错误:使用地址绑定套接字时已经使用的地址但是`netstat`显示了端口号

Dur*_*rin 51 c sockets linux

我试图在端口号绑定我的套接字(服务器套接字)8000.它起作用并为我做了工作.在代码的最后我也关闭了套接字.在下一刻我再次运行我的代码,它向我显示该地址已被使用.我已经打印了错误值的含义,strerror(errno);以查看我的代码是否在每个点都正常工作.要检查端口是否空闲,我使用了netstat它,但它显示端口号8000是免费的.它发生在我身上很多次.每次我等待几秒钟然后它再次开始工作.我正在使用c语言.那么我的操作系统对于这种行为的原因是什么?

再过几秒钟后,我运行代码然后就可以了.

anirudh@anirudh-Aspire-5920:~/Desktop/testing$ sudo ./a.out 
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1348/lighttpd   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      984/sshd        
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      1131/cupsd      
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      1211/mysqld     
tcp6       0      0 :::22                   :::*                    LISTEN      984/sshd        
tcp6       0      0 ::1:631                 :::*                    LISTEN      1131/cupsd      
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ sudo ./a.out 
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ 
Run Code Online (Sandbox Code Playgroud)

icf*_*ntv 59

我也遇到过同样的问题.这是因为您正在关闭与套接字的连接,而不是套接字本身.套接字可以进入TIME_WAIT状态(以确保所有数据都已传输,如果可能,TCP保证传送)并且最多需要4分钟才能发布.

或者,对于真正的详细/技术说明,请查看此链接

确实可能很烦人,但没有真正的方法,它不是一个错误.

  • 您链接的页面上有可能的解决方案.您可以对套接字使用SO_REUSEADDR选项.请参阅setsockopt:http://linux.die.net/man/3/setsockopt (13认同)

hip*_*ipe 22

试试这样的netstat : netstat -ntp,没有-l.它将显示TIME_WAIT状态中的tcp连接 .

  • 更好的是,使用`ss -npt`. (5认同)

Sup*_*mee 21

我知道问题被问到已经有一段时间但是我找到了一个解决方案:

int sockfd;
int option = 1;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
Run Code Online (Sandbox Code Playgroud)

这使套接字能够立即重用.

如果这是"错误的",我道歉.我对套接字不太熟悉

  • 报价更多的是"如果它运作没有错"的那种东西.我意识到这可能不是首选方式,如果有人知道我会有兴趣听到的"正确"方式. (10认同)
  • 1是什么意思? (4认同)
  • 这是前一段时间,所以如果我错了,请纠正我,但我相信这是使用的,因为当您希望套接字不停留时,必须是“非零”。我找不到任何具体内容,但您可以在以下位置阅读更多相关信息:https://www.ibm.com/support/knowledgecenter/en/SSB23S_1.1.0.15/gtpc2/cpp_setsockopt.html (2认同)

Jér*_*ler 8

如前所述,您的套接字可能进入TIME_WAIT状态.Thomas A. Fine 在这里很好地描述了这个问题.

总结一下,套接字关闭过程如下图所示:

套接字关闭过程

托马斯说:

查看上图,很明显,TIME_WAIT如果远程端启动闭包,则可以避免.因此,服务器可以通过让客户端先关闭来避免问题.必须设计应用程序协议,以便客户端知道何时关闭.服务器可以安全地关闭以响应来自客户端的EOF,但是如果客户端不正常地离开网络,它还需要在期望EOF时设置超时.在许多情况下,只需在服务器关闭前等待几秒即可.

使用SO_REUSEADDR通常建议在互联网上,但托马斯补充说:

奇怪的是,使用SO_REUSEADDR实际上可能会导致更难的"已使用的地址"错误.SO_REUSADDR允许您使用卡住的端口TIME_WAIT,但您仍然无法使用该端口建立与其连接的最后一个位置的连接.什么?假设我选择本地端口1010,并连接到foobar.com端口300,然后在本地关闭,留下该端口TIME_WAIT.我可以立即重用本地端口1010连接除foobar.com300端口以外的任何地方.


小智 6

只需输入

unlink [SOCKET NAME]
Run Code Online (Sandbox Code Playgroud)

在终端中,则错误应该不再存在.

  • 这是针对 Unix 域套接字的。问题是关于 TCP 套接字的。 (5认同)