[英]In Linux, how do I know if an ACK is received to a certain TCP packet?
簡而言之:在Linux中,如何確保收到某個TCP數據包的ACK消息?
全文:
我正在調試Asterisk / OpenH323 < - > Panasonic IP-GW16問題。
H323連接涉及兩個會話:H225.0和H245。 這些只是兩個TCP會話,其中傳輸了一些數據。
我們稱它們為Session 1
(H225.0)和Session 2
(H245)。
Session 1
具有眾所周知的TCP端口號1720,而Session 2
端口在運行時選擇。
控制流程如下:
Session 1
(TCP / 1720),並通過Session 1
發送SETUP消息,其中包含Panasonic將收聽的port 2
。 Session 1
向Panasonic發送了一條CALL PROCEEDING消息 port 2
Session 1
發送TCP ACK。 port 2
上打開TCP Session 2
port 2
。 步驟2和3的順序很重要:除非在step 2
收到CALL PROCEEDING消息,否則Panasonic不會收聽port 2
step 2
。
但在OpenH323代碼中, step 2
和step 5
距離只有幾行。
這就是為什么連接sometimes
在調試模式下工作並且在發布時quite never
不起作用的原因。
在數據包轉儲中可以清楚地看到它。 我做了一系列的實驗,在52個中的52個案例中,如果step 5
在step 4
之前進行,則連接失敗; 如果沒有,連接成功。
除了step 4
中的ACK之外,沒有其他消息從Panasonic發送,並且似乎Asterisk可能知道port 2
被監聽的唯一方式是接收該ACK。
當然我可以實現定時等待,但我想要一個更清潔的解決方案。
所以問題再次出現:在step 2
通過TCP連接發送消息后,如何知道是否收到包含該消息的數據包的ACK?
在這個特定的情況下,我會說你會發現你的tcp_info
結構將保持非零tcp_info.tcpi_unacked
。 你可以通過getsockopt(TCP_INFO)
得到這個。
注意:界面不穩定。
TCP級別的ACK由操作系統發送,並且可以在進程讀取數據之前發送。 因此,如果您收到ACK,則並不意味着遠程應用程序對該消息采取行動或甚至通知它存在。
試想一下:如果TCP確認我們是消息確認,那么應用程序應該讀取()消息,處理消息(可能需要一段時間),然后調用“read_ok”系統調用。 據我所知,使用標准套接字API是不可能的。
您可以使用SIOCOUTQ ioctl(man 7 tcp)檢查是否有任何未包裝的數據。 但它不是你問題的可靠解決方案。
你確定這是h323的工作方式嗎? 如果port2無效或被另一個連接占用怎么辦? 應該發回確認或錯誤。
雖然如果松下使用可能解釋它的專有O / S,時序似乎很奇怪。
澄清 - AIUI - 如果松下運行“正常”操作系統,它在第4階段發送的ACK將在Panasonic的軟件read()
來自控制TCP套接字的數據后立即發生。
類似地,在Asterisk服務器收到來自Panasonic的ACK之前,對write()
(在步驟2中)的OpenH323代碼調用不應返回( 假設它不是非阻塞套接字 !)。 這就是你應該知道已收到ACK的方式。
從本質上講,松下似乎沒有在第二個套接字上執行listen()
,直到它read()
CALL PROCEEDING
消息。 它看起來像競爭條件 - 有時Open323會在另一端准備好之前嘗試connect()
。
發生這種情況時,你會在OpenH23端獲得ECONNREFUSED
嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.