c - 尝试重新绑定已经关闭的侦听套接字失败(EADDRINUSE)?
问题描述
以下是我的测试夹具的本质 -
SetUp()
{
g_listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/* localhost is the server */
bind(g_listen_sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
listen(g_listen_sock, max_connections);
}
testcase()
{
hdl = accept(g_listen_sock, NULL, NULL);
-- send()/recv() data on the socket --
}
TearDown()
{
shutdown(g_listen_sock, SHUT_RDWR);
close(g_listen_sock);
g_listen_sock = INVALID_SOCKET;
}
在应用程序的正常使用中,监听套接字在应用程序的生命周期内只绑定一次,但是测试设置会反复打开和关闭监听套接字。测试用例的第一次迭代工作正常,但随后的迭代在使用errno == 98
EADDRINUSE 的 bind() 调用时失败。
我该如何避免这种情况?理想情况下,该解决方案不需要我拥有单独的代码测试版本,例如在测试时使用 SO_REUSEADDR。
PS - 相同的代码在 Windows 上运行良好,bind() 失败发生在 Linux 上。
解决方案
您要解决的是网络 TCP 层的内置功能。linux 内核不允许您重新绑定该套接字,因为关闭的套接字将处于 TIME_WAIT 状态。除了使用SO_REUSEADDR
(正如您已经指出的那样)或为每个测试使用不同的端口(听起来您也不想这样做)之外,您无能为力。
不幸的是,TCP 的设计不是为了连续多次关闭和打开同一个 IP/端口进行测试,所以如果你仍然想进行这种测试,你将不得不选择你的毒药。
另请参阅此答案以更深入地探索您的问题。
推荐阅读
- java - 为什么Java时间戳解析以毫秒为前缀0?
- sql - 我们如何将我们的数字格式转换为欧洲数字格式并且在 Oracle 中仍然是数字类型
- css - 使用 NavBar 组件时 id 和 class 的区别?
- azure - 从流量管理器访问应用服务 - 错误
- python - 没有得到 django 密码重置 password_reset_confirm 预期错误
- html - 如何使转换后的排版响应图像
- react-native - 导航到屏幕时的数据更新
- javascript - 将一组图像添加到弹出框
- php - JWT Key -> exp 声明向我显示一个异常
- glsl - GLSL 线型 - 改变颜色