套接字编程:connect() 挂起不存在的 IP
socket programming: connect() hangs for a non-existent IP
connect()
而如果 IP 不存在,则返回正套接字描述符
Connection::Connection(string& ip) : sock(0), status(0), conn(0){
struct sockaddr_in sin;
sock = socket(AF_INET, SOCK_STREAM, 0);//socket() returns -1 on failure.
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = inet_addr(ip.c_str());
cout << "sock: " << sock << endl;
//fcntl(sock, F_SETFL, O_NONBLOCK);
if(sock != -1){
conn = connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in));
cout << "conn: " << conn << endl;
if ( conn != 0){
status = -2;
}
}
else{
status = -1;
}
}
出于调试目的,我把cout
放在socket()
和connect()
之后。我已经测试过,如果向构造函数提供了不存在的 IP,cout << "conn: " << conn << endl;
永远不会执行并继续等待。
这些代码适用于现有的 IP。
我在某处读到O_NONBLOCK
socket descriptor
设置将解决悬挂问题。是的,它确实存在,但出现了一个新问题;我什至无法连接到现有的IP。
请帮助我解释为什么会发生这种情况以及如何解决此问题。
我认为您需要退后一步,考虑一下IP是否"存在"是什么意思。
当您调用connect
时,操作系统将向目标 IP 发送一个数据包(SYN
数据包)。它不知道IP是否"存在"。事实上,这个概念没有明确定义——它可能被分配,也可能不会被分配。设备可能已打开或未打开或插入。它可能位于 DHCP 池中,其中已分发或尚未分发该 IP 的租约。操作系统对此一无所知。操作系统只知道它是否得到回复。并且任一方向都可能存在数据包丢失,因此有必要进行回复。
从广义上讲,操作系统可以获得三种类型的回复(您可以使用tcpdump
或wireshark来查看正在发生的回复):
-
目标 IP 使用
SYN+ACK
数据包进行回复。这是三方握手的下一阶段。目标 IP 显然正常工作。 -
目标 IP 回复
RST
。这意味着"走开";您会看到"连接被拒绝"。 -
目标 IP 或某些中间路由器回复 ICMP 主机无法访问或网络无法访问,在这种情况下,您将看到主机无法访问或网络无法访问。如果无法访问主机或网络,则不能保证会发生这种情况。
还有第四种可能,就是根本没有收到答复。在这种情况下,connect
等待并重试几次,最后超时。这就是你所看到的。过滤掉防火墙中的 ICMP 会将上述情况 (3) 转换为这种情况,但请务必注意,无论如何都会发生这种情况。因此,这是您应该准备好处理的自然状态。
使用非阻塞connect()
(通过先设置O_NONBLOCK
)使connect()
立即返回 - 甚至在功能正常的 IP 建立连接之前。在任何情况下,您都需要留出一些时间才能建立连接。通过慢速链接或数据包丢失,正常运行的 IP 可能需要数十秒才能连接。因此,在这种情况下,您需要实现自己的超时(例如,通过在套接字上select()
-ing)。(无论如何在Linux下)没有将自己的超时设置为connect()
的选项,因此如果要更改超时,则必须使用非阻塞连接来实现它。斯蒂芬斯(一本很棒的书 - 购买它)关于非阻塞connect()
的详细信息在这里。
- 挂起和取消挂起一个文件DLL
- 我们可以访问一个不存在的联盟的成员吗
- C++:对不存在的命名空间使用命名空间指令
- 如何防止C++遗留代码中的挂起指针
- g++ 说函数不存在,即使包含正确的标头
- Poco::Net::FTPClientSession 在 open() 方法上挂起 129 秒,如果 ftp 主机不存
- 带有 QSharedMemory 的 IPC,如果其中一个进程挂起,则存在风险
- cudaMemcpyToSymbol只是挂起,永远不会返回.GPU 处理速度为 100%.代码在 K40 上工作正常,但
- 当不存在这样的构造函数时,将类传递给构造函数.它为什么起作用
- 套接字编程:connect() 挂起不存在的 IP
- 运行需要输入而不挂起的命令,但仍允许输入
- QGraphicsScene - 添加带有少量不透明点的大透明像素图时,应用程序会挂起很长时间
- 不断更新GUI表单元素,使表单不会挂起
- 如何设置pthread_cond_signal以使程序不会挂起?
- Git挂起的更改不起作用
- 当从matlab使用boost::线程时,挂起和/或段错误,而不是直接调用时
- 如果 ssl::stream<tcp::socket 有挂起的操作,我是否不允许删除它>?
- Qt程序挂起(不响应),直到函数结束,然后再次开始工作
- QTableWidget不在焦点时挂起/暂停
- OpenCV视频捕获在相机断开连接时挂起/冻结,而不是返回"False"