问题描述
嗨,我是 C++ winsock2 套接字的新手,我已经被困在这里一段时间了。
如何从作为参数传递的套接字/文件描述符获取套接字是否已连接、绑定、侦听或关闭。
注意:我想在不尝试绑定/连接/侦听/关闭套接字的情况下找出套接字状态,因为这将返回结果并执行操作。示例:如果我想检查套接字是否连接到服务器,我应该尝试连接并获得我不想要的结果。
我正在努力实现这样的目标。
// Using Winsock2 API.
bool isSocketBound(SOCKET s) {
// Check if socket is bound without attempting to bind.
// The code which I'm not able to figure out.
return isBound;
}
// Same goes for the other functions.
提前致谢。
解决方法
如何从作为参数传递的套接字/文件描述符获取套接字是否已连接、绑定、侦听或关闭。
没有单个套接字 API 来查询 SOCKET
的当前状态。但是:
-
getsockname()
会告诉你套接字是否在本地绑定。 -
getpeername()
会告诉您套接字是否已连接到远程对等方。 -
getsockopt()
与SOL_SOCKET:SO_ACCEPTCONN
选项将告诉您面向连接(即 TCP)SOCKET
是否listen()
'ing。>或者,如果您尝试在
connect()
的套接字上listen()
,您将收到WSAEINVAL
错误。如果您尝试在listen()
的套接字上connect()
,您将收到WSAEISCONN
错误。或者,如果套接字至少在本地绑定,那么您可以使用
getsockname()
获取其本地 IP/端口,然后使用GetTcpTable()
、GetTcpTable2()
或 {{3} } 以查明该 IP/端口是否处于LISTENING
状态。 -
如果
SOCKET
已在本地关闭,则SOCKET
一开始就无效,因此您无法查询任何内容。您能做的最好的事情就是在使用完毕后将SOCKET
设置为INVALID_SOCKET
,然后在需要时检查该条件。另一方面,如果套接字已远程关闭但尚未在本地关闭,则SOCKET
仍然有效,但无法查询其关闭状态。知道套接字是否已被对等方关闭的唯一方法是recv()
操作是否报告收到 0 个字节,或者send()
操作是否因连接错误而失败,或者您是否正在使用 { {1}} 处于异步模式(SOCKET
或WSAAsyncSelect()
)并收到WSAEventSelect()
通知。
注意:我想在不尝试绑定/连接/侦听/关闭套接字的情况下找出套接字状态,因为这将返回结果并执行操作。示例:如果我想检查套接字是否连接到服务器,我应该尝试连接并获得我不想要的结果。
为什么不简单地在自己的代码中跟踪状态?如果您 FD_CLOSE
一个 bind()
并且它成功,那么您知道它是本地绑定的。如果您 SOCKET
并且成功,那么您就知道它已在本地绑定并连接到远程服务器。您应该在 connect()
变量旁边维护一个 state
变量,并随着您在 SOCKET
上执行的每个状态更改操作更新 state
。