C 按顺序连接()、接受()和选择()

C 按顺序连接()、接受()和选择(),c,tcp,C,Tcp,我是C的新手。我刚刚注意到,只要TCP三向握手完成,客户端的connect()函数就可以返回。我的意思是connect()甚至可以在调用服务器端的accept()之前返回(如果我错了,请纠正我)基于这些知识,我的问题是,当我随后在客户端调用select()并观察文件描述符等待其可写时,当select()成功返回时,这意味着服务器端已经调用了accept(),现在我可以安全地写入服务器端,正确的?非常感谢您抽出时间 int flags = fcntl(fd, F_GETFL); flags |=

我是C的新手。

我刚刚注意到,只要TCP三向握手完成,客户端的
connect()
函数就可以返回。我的意思是
connect()
甚至可以在调用服务器端的
accept()
之前返回(如果我错了,请纠正我)

基于这些知识,我的问题是,当我随后在客户端调用
select()
并观察文件描述符等待其可写时,当
select()
成功返回时,这意味着服务器端已经调用了
accept()
,现在我可以安全地写入服务器端,正确的?非常感谢您抽出时间

int flags = fcntl(fd, F_GETFL);

flags |= O_NONBLOCK;

fcntl(fd, F_SETFL, flags);

if (connect(fd, (struct sockaddr *)saptr, salen) < 0)
{
    if (errno != EINPROGRESS)
        /* error_return */
}

fd_set set;
FD_ZERO (&set);

FD_SET (fd, &set);

select (FD_SETSIZE, NULL, &set, NULL, &timeout)
/* Here, if select returns 1, that means accept() is already called 
   on the server side, and now I can safely write to the server, right? */
int flags=fcntl(fd,F_GETFL);
标志|=O|U非块;
fcntl(fd、F_设置、标志);
如果(连接(fd,(结构sockaddr*)saptr,salen)<0)
{
if(errno!=EINPROGRESS)
/*返回错误*/
}
fd_集;
FD_零位(&set);
FD_集(FD,和集);
选择(FD_SETSIZE、NULL和set、NULL和timeout)
/*这里,如果select返回1,则表示已调用accept()
在服务器端,现在我可以安全地写入服务器了,对吗*/
'我的意思是connect()甚至可以在服务器上的accept()之前返回 一方称为’

是的,它可以,而且确实如此

当我在客户端调用select()并查看文件时 描述符等待它可写,当select()成功时 返回,这意味着服务器端已经调用了accept()和 现在我可以安全地写到服务器端了,对吗

当然。写下:)

当select()成功返回时,这意味着服务器端已经调用了accept()

不,不一定<代码>连接()在连接尝试成功或失败后完成时返回。在远程端,这由网络堆栈在任何应用程序的上下文之外处理。随后的
accept()
本身不会产生额外的通信

现在我可以安全地写到服务器端了,对吗

“安全”有各种各样的含义,但如果您的意思是本地端可以在不阻塞的情况下写入至少一个字节,那么是的,
select()
向您保证这一点。您成功写入的任何内容都将通过线路发送到远程端。它可能会在那里缓冲一段时间,这取决于远程端软件的行为。该软件是否已
accept()
ed连接与该问题没有直接关系


更新:还要注意,网络堆栈维护一个每个套接字的已建立连接队列,这些连接尚未
accept()
ed(其待办事项)。这种排队行为是服务器可能不会在连接建立后立即
accept()
连接的原因之一,特别是在负载较重的情况下。

“我的意思是,connect()甚至可以在服务器端的accept()调用之前返回”-当然,是的。回答很好。可能会考虑在 ListNe()/代码>的积压中添加一个注释。约翰·布林格谢谢你的回答。我只是做了个小实验来测试。是的,
select
的返回并不一定意味着服务器端已经调用了
accept