【发布时间】:2017-02-25 19:36:26
【问题描述】:
我的实验表明,我可以在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。所以,是的,我的第一个实验是不公平的(连接到快速 localhost),但我仍然认为可以使用“connect()”旁边的“write()”:如果write() 返回 -1 和 EAGAIN,我等待EPOLLOUT 并重试写入。但我同意,这是肮脏无用的做法。
【问题讨论】:
-
IIRC 用于 nin 阻塞套接字,connect() 的行为不同。您应该等待(通过选择或轮询)套接字变为可写
-
显然调用之间的连接已完成。你真是幸运。不要写这样的代码。除非您有多个 aocket,否则在非阻塞模式下进行连接确实没有意义。以阻塞模式连接,然后切换。
-
NB 您使用
poll()的方法没有任何“过时”之处。这只是正确的。正确性不是时间的函数。 -
重新编辑,您现在提到的方法与您询问的方法不同。