向Windows网络编程专家提问。
当我使用这样的伪代码时:
reconnect:
s = socket(...);
// more code...
read_reply:
recv(...);
// merge received data
if(high_level_protocol_error) {
// whoops, there was a deviation from protocol, like overflow
// need to reset connection and discard data right now!
closesocket(s);
goto reconnect;
}
内核是否取消关联并释放从NIC“物理”接收的所有数据(因为它必须真正存在于内核内存中,等待用户级别使用recv()读取它),当我closesocket()时?好吧,逻辑上应该是因为数据不再与任何内部对象相关联,对吧?
因为我真的不想浪费未知的时间进行干净关机,例如“调用recv()直到返回错误”。这没有意义:如果它永远不会返回错误,比如说,服务器会继续永久发送数据并且不会关闭连接,但这是不好的行为?
我很想知道它,因为我不希望我的应用程序在任何地方导致内存泄漏。这种强制重置连接的方式,仍然可以发送未知数据量正确吗?
//问题的可选添加:如果这个方法被认为对Windows是正确的,对于符合UNIX的操作系统,它是否可以被认为是正确的(将closesocket()
更改为close()
)?
答案 0 :(得分:1)
Windows(或任何操作系统)中的内核驱动程序(包括tcpip.sys
)应该可以在所有情况下避免内存泄漏,无论您在用户模式下执行什么操作。我认为开发人员已经绘制了可能的状态,包括错误状态,以确保资源不会泄露。至于用户模式,我不完全确定,但我不认为资源在您的过程中泄露。
套接字只是Windows中的文件对象。当您关闭文件的最后一个句柄时,IO管理器会向拥有该文件的驱动程序发送IRP_MJ_CLEANUP
消息,以清除与其关联的资源。与套接字关联的接收缓冲区将与文件对象一起释放。
在closesocket
documentation中确实说取消了挂起的操作,但是在函数返回后异步操作可能会完成。这听起来像是在使用时关闭套接字是受支持的场景,并且不会导致内存泄漏。
答案 1 :(得分:0)
没有泄漏,您没有义务在关闭前阅读EOS流。如果发送者在您关闭后仍在发送,最终将获得“连接重置”。