c++ - 将现有套接字重新连接到新服务器所需的最少工作是什么?

标签 c++ linux sockets

给出以下伪代码...

int sock = socket( AF_INET, SOCK_STREAM, 0 );
sockaddr_in si;
si.sin_family = AF_INET;
si.sin_port = 0;
si.sin_addr.s_addr = htonl( inet_network( "127.0.0.100" ) );
bind( sock, (sockaddr*)&si, sizeof si );
...
struct sockaddr_in peer_addr;
inet_pton(AF_INET, "127.0.0.200", &peer_addr.sin_addr);
peer_addr.sin_family = AF_INET;
peer_addr.sin_port = htons( 9000 );
connect( sock, (sockaddr*)&peer_addr, sizeof peer_addr) );

...假设 connect() 成功,随后对等方关闭与 listen() 使用的各自套接字并由 accept() 返回,是否可以重用 sock 作为具有不同对等方地址的子序列 connect() 的参数?

从实验上来看,答案似乎是“否”:尽管第二个 connect() 返回 0,但我尝试连接的第二个对等点永远不会从 accept() 返回。知识渊博的回答者可以解释这里出现问题的本质吗? 0 返回值应该表示成功,那么为什么对等方 accept() 永远不会解除阻止?

我可以做些什么来重用sock来连接到第二个对等点吗?或者第二个 connect() 必须使用 socket() 新创建的套接字来完成吗? (我已验证这样做有效)

最佳答案

What is minimal work needed to reconnect existing socket to new server?

无限。这是不可能的。

is it possible to reuse sock as the argument to a subsequenet connect() with a different peer address?

没有。一旦调用 connect(),即使失败,也无法重新连接 TCP 套接字。您必须关闭它并创建一个新套接字。原因之一是,如果套接字未绑定(bind),connect() 会绑定(bind)它,并且该绑定(bind)是根据到目的地的 IP 路由选择的,而第二个目的地的 IP 路由可能不同。

although the second connect() returns 0

很难相信。你确定吗?

the second peer to which I try to connect never returns from listen().

listen() 不会阻塞。你的意思是accept()吗?

Can a knowledgeable answerer explain the nature of what is going wrong here?

您的意思一定是 accept(),而且很难相信第二个 connect() 返回零。 connect() 应该返回 -1,errno == EISCONN(或 Windows 上的 WSAGetLastError() == WSAEISCONN)。

编辑 但是,在非阻塞套接字上第二次调用 connect() 用于检测第一次 connect() 是否已完成。这种技术在所有旧书中都有,但现在我们有了 SO_ERROR,正确的技术是检查 getsockopt(SO_ERROR) 是否从第一个 connect() 获得了 EAGAIN/EWOULBLOCK。当您收到来自 select() 的写入通知或来自 (e)poll() 的写入或错误通知时,您将执行这些检查。因此,在您的情况下发生的所有事情都是第二个 connect() 确认了第一个 connect() 的成功,并忽略了不同的目标地址/端口。

The 0 return value supposedly indicates success, so why might the peer listen() never unblock?

无论外观如何,第二个 connect() 失败了,因此服务器没有理由执行任何操作,更不用说从 accept() 返回了。

Is there something I can do to reuse sock to connect to a second peer?

没有。

Or must that second connect() be done with a socket freshly-created by socket()?

是的。

关于c++ - 将现有套接字重新连接到新服务器所需的最少工作是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46800357/

相关文章:

c++ - 命令行参数类似于 C++ 中的用户输入

linux - 在 bash 脚本中用下划线替换连字符

linux - 关于loader如何在运行时定位库的问题

linux - 用sed替换多行变量

python - 使用 Flask-SocketIO 自定义握手数据

c++ - 如何在 QVBoxLayout 中显示 QString

c++ - C++17 的 std::inserter 替代品

c++ - 错误 LNK2001 : unresolved external symbol in cocos2d-x lua support

c# - UDP 广播发送在 UWP 中不起作用

c - 嗅探 C 中的所有网络流量