我的实验表明,我可以在 connect()
调用之后写入非阻塞套接字,尚未建立 TCP 连接,并且在连接发生后,对等方正确接收写入的数据(异步)。这在 Linux/FreeBSD 上有保证吗?我的意思是,当连接仍在进行时,write()
会返回 > 0 吗?或者也许我很幸运,在 connect()
和 write()
调用之间成功建立了 TCP 连接?
实验代码:
int fd = socket (PF_INET, SOCK_STREAM, 0);
fcntl(fd, F_SETFL, O_NONBLOCK)
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(_ip_port.port);
addr.sin_addr.s_addr = htonl(_ip_port.ipv4);
int res = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
// HERE: res == -1, errno == 115 (EINPROGRESS)
int r = ::write(fd, "TEST", 4);
// HERE: r == 4
附注
我在单线程中处理多个监听和连接套接字(传入和传出连接)并通过 epoll 管理它们。通常,当我想创建新的传出连接时,我会调用非阻塞 connect()
并等待 EPOLLOUT
(epoll 事件),然后 write()
我的数据。但我注意到我可以在 EPOLLOUT 之前开始写入并获得适当的结果。我可以相信这种方法还是应该使用我的旧时尚方法?
P.P.S。
我在延迟 170 毫秒的远程主机上重复了我的实验,并得到了不同的结果:write()
(就在 connect()
之后)返回 -1,errno = = EAGAIN
。所以,是的,我的第一个实验并不公平(连接到快速本地主机),但我仍然认为可以使用 connect()
旁边的“write()
” :如果 write()
返回 -1 和 EAGAIN,我会等待 EPOLLOUT
并重试写入。但我同意,这是肮脏且无用的方法。
最佳答案
我可以在 connect() 调用之后、TCP 连接建立之前向套接字写入 write() 吗?
当然,你可以。很可能会失败。
根据 POSIX specification of write()
:
[ECONNRESET]
A write was attempted on a socket that is not connected.
根据 Linux man page for write()
:
EDESTADDRREQ
fd refers to a datagram socket for which a peer address has not been set using
connect(2)
.
如果 TCP 连接尚未完成,您的 write()
调用将会失败。
关于sockets - 我可以在 connect() 调用之后、TCP 连接建立之前对套接字进行 write() 操作吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40075878/