簡體   English   中英

在Linux中,我如何知道某個TCP數據包是否收到了ACK?

[英]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端口在運行時選擇。

控制流程如下:

  1. 松下稱為Asterisk:它向Asterisk打開Session 1 (TCP / 1720),並通過Session 1發送SETUP消息,其中包含Panasonic將收聽的port 2
  2. Asterisk通過Session 1向Panasonic發送了一條CALL PROCEEDING消息
  3. 松下開始收聽port 2
  4. Panasonic通過Session 1發送TCP ACK。
  5. Asterisk在port 2上打開TCP Session 2 port 2

步驟2和3的順序很重要:除非在step 2收到CALL PROCEEDING消息,否則Panasonic不會收聽port 2 step 2

但在OpenH323代碼中, step 2step 5距離只有幾行。

這就是為什么連接sometimes在調試模式下工作並且在發布時quite never不起作用的原因。

在數據包轉儲中可以清楚地看到它。 我做了一系列的實驗,在52個中的52個案例中,如果step 5step 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM