作为一名网络工程师,我对TCP操作非常熟悉。作为一名程序员,我涉足套接字编程,但从未编写任何生产服务。
我们有一个供应商系统,可与PTZ(平移/倾斜/变焦)相机集成。相机看病人。摄像机数据被送到供应商服务器。供应商服务器将摄像机数据中继到客户端。 (它做得更多,但这是一个简单的情况。)如果客户想要调整摄像头,客户端会向供应商服务器上的自定义服务发送自定义命令。服务器解释该命令并将其发送到摄像机。相机移动。
我们遇到服务器上的PTZ服务崩溃的问题。在测试期间,通过网络捕获,我们发现服务崩溃的时间nmap
执行半开(胚胎)连接 - nmap发送SYN,服务器回复SYN / ACK,nmap没有发送最终ACK。服务器发送重复的SYN / ACK尝试完成会话并失败。
我想要了解的内容:服务使用listen
来监视TCP连接,然后使用accept
接受连接。 listen
告诉服务在什么时候有一个新的连接,准备好accept
?在listen
将其传递给要accept
的服务之前,是否需要完成TCP连接?或者服务器是否需要在listen
告诉服务之前返回SYN / ACK?
如果握手需要完成 - SYN,SYN / ACK,ACK - 在listen
告诉服务之前,那么我可能会走错路。如果套接字只需要进入SYN / ACK,则服务处理不完整的会话可能会出现问题。其他测试,我们完成TCP会话并发送伪造数据试图使服务崩溃 - 并未导致服务失败。但重复的nmap
测试非常可靠地崩溃了,所以我倾向于半开连接问题。
答案 0 :(得分:0)
listen()
本身只是创建积压队列,打开绑定端口进行通信,然后退出。 在幕后,套接字堆栈现在被动地侦听OS层的连接,缓存积压队列中的挂起连接并完成他们的握手。只有完全建立的关联可用于accept()
,WSAAccept()
和AcceptEx()
。
退出{{1}后,取决于应用程序代码用于套接字I / O的模式(阻塞,非阻塞,重叠I / O或I / O完成端口),代码可以:
(阻止)调用listen()
或accept()
并让它阻塞,直到它从队列中检索连接。
(非阻止)使用WSAAccept()
,select()
或WSAAsyncSelect()
在连接准备好并等待使用WSAEventSelect()
或accept()
。
(overlapped / iocp)调用WSAAccept()
开始异步接受,然后等待事件/完成通知,指示已从队列中检索到连接。
答案 1 :(得分:0)
在什么时候,listen会告诉服务有一个新的连接,准备接受了吗?
从不。
在将侦听传递给要接受的服务之前,TCP连接是否需要完成?或者服务器是否需要在监听告诉服务之前返回SYN / ACK?
这一切都没发生。 listen()
只是将套接字置于LISTEN状态,并使TCP开始接受连接并将它们放入积压队列中。与服务通信的是accept()
:它在积压队列为空(基本上)时阻塞,然后返回第一个条目并在其周围构建一个新的套接字。
如果握手需要完成 - SYN,SYN / ACK,ACK - 在监听告诉服务之前,那么我可能会走错路。
需要在accept()
将新套接字返回服务之前完成。
如果套接字只需要进入SYN / ACK,则服务处理不完整的会话可能会出现问题。
不是问题。它的行为并非如此。
其他测试,我们完成TCP会话并发送虚假数据试图让服务崩溃 - 但没有导致服务失败。
QED。
但重复的nmap测试非常可靠地崩溃了,所以我倾向于半开连接问题。
请定义'崩溃'。