SOCK_STREAM socket listen()导致发送TCP syn/ack

SOCK_STREAM socket listen()导致发送TCP syn/ack,c,sockets,network-programming,freebsd,C,Sockets,Network Programming,Freebsd,我设置了一个套接字来接受与的TCP连接 socket(AF_INET, SOCK_STREAM, 0) 然后我调用bind(),listen()和accept() 问题是,当我调用listen()时,它会导致一个SYN/ACK数据包被发送到客户端。我以为在调用accept()之前不会发生这种情况,但更糟糕的是,SYN/ACK数据包的确认数没有增加1 这是什么原因造成的,我如何修复它 谢谢 作为旁注-我的TCP连接是非对称的有关系吗?在您的计算机上,TCP的实现可能会选择在您呼叫侦听时实际“接受

我设置了一个套接字来接受与的TCP连接

socket(AF_INET, SOCK_STREAM, 0)
然后我调用
bind()
listen()
accept()

问题是,当我调用listen()时,它会导致一个SYN/ACK数据包被发送到客户端。我以为在调用accept()之前不会发生这种情况,但更糟糕的是,SYN/ACK数据包的确认数没有增加1

这是什么原因造成的,我如何修复它

谢谢


作为旁注-我的TCP连接是非对称的有关系吗?

在您的计算机上,TCP的实现可能会选择在您呼叫
侦听时实际“接受”传入连接。这实际上是有道理的,以避免由于“懒惰”接受而造成不必要的延迟。提醒您,
listen
的参数之一是所谓的积压数量,即“缓冲”接受未决的数量


关于syn+ACK数据报中ACK的递增。我不记得协议的状态,但这可能是握手过程中的正确行为。

这是TCP“backlog”队列的正常操作。这是一个连接队列,堆栈已完成,但应用程序尚未接受。此队列的大小由第二个参数设置为listen(),尽管平台可以向上或向下(通常向上)调整它


无论您对序列号所观察到的是什么,都必然是正确的行为,否则什么都不起作用。

如其他答案和评论中所述,这是TCP实现的实际标准行为

如果您坚持通过在应用程序中接受传入连接来显式完成TCP握手,那么您就有了一个依赖于平台的解决方案


对于Windows堆栈,您可以在侦听套接字上设置
SO\u CONDITIONAL\u ACCEPT
socket选项。请参阅。

如果这是一个主流TCP实现,则不太可能是行为不端。在服务器调用listen()之前,客户端是否正在尝试连接?如果是这样的话,如果它没有超时,可能事件的顺序有点不寻常(但决不是非法的),这意味着正确的行为与您预期的有所不同。嗯,这是事实。实际上,我正在拦截一些流量,并在客户端尝试连接(客户端是wget)之后,打开套接字侦听()。这有点像一个即时端口转发,我正在尝试实现一个导致问题的最小示例。@Derek你看起来很困惑。通常,每个接受的套接字(即每个客户端)都有一个线程,因此没有什么可混淆的。因此,每个套接字仍然需要一个线程,可能两个,一个用于读取,一个用于写入。或者可能使用poll()。您当然不希望多个线程写入同一个套接字:交错可能以任何方式发生。您所知道的是,每个send()都是原子的,也就是说,所有的数据都在一起。我同意增加它是正确的行为。我总是假设它发生在连接的“接受”阶段。@Derek它确实发生在连接的“接受”阶段,但该阶段通常发生在应用程序调用accept()函数之前。如果backlog队列设置为零,这是否会迫使内核等待接受某些内容,直到我准备隐式调用accept()。@Derek否。内核将默默地强制执行其最小值,即5或500。你为什么要零?