我有一个应用程序,其主要目的是将RTP流转换为HTTP流。一个线程正在接收RTP数据包并将它们写入循环缓冲区,另一个线程充当迷你网络服务器并通过从该缓冲区读取来回答HTTP请求(一次只能发生一个GET请求)。
一旦收到GET,这个HTTP线程就是一个简单的循环,只要循环缓冲区中有东西就调用send()。但有时,send()会在一段时间内(例如> 1s)阻塞,从而产生音频丢失。
要清楚,RTP数据包是实时到达的,此处没有上溢或下溢。 HTTP套接字是故意阻塞的,因为预期接收器在不需要音频时(足够自己的缓冲区)使用TCP来调节其流量。但是,HTTP客户端并没有被音频所淹没,因为RTP源也是实时的。
但显然,还有其他事情发生了,而且我已经观察到Linux,MacOS和Windows(代码适用于所有这些)以及两种不同的网络拓扑。
我想知道send()长块是否不是由于TCP流量控制之外的其他因素,就像我在线程阻塞发送()时发生的事情所遗漏的那样
答案 0 :(得分:2)
获取wireshark跟踪,以便您可以看到TCP停顿发生的位置。我怀疑发生的事情是以下任何一种情况:
您实际发送的速度比客户端消耗的速度快。我想你已经排除了......
更可能的情况是,IP数据包丢失,TCP卡在等待ACK,超时,然后重新发送。与此同时,您的发送线程正试图将更多数据填充到套接字中,并且它会被备份并最终阻塞。
您可以做的一件简单事情是尝试增加发送的套接字上的发送缓冲区(if joined in Recreation
)。此值指定应用程序在阻止之前可以写入套接字的未传输字节数。如果可能,请增加客户端的接收缓冲区(Private Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32" (ByVal uFormat As Long) As Long
Private Declare PtrSafe Function GetClipboardData Lib "user32" (ByVal uFormat As Long) As Long
Private Declare PtrSafe Function OpenClipboard Lib "user32" ( ByVal hwnd As Long) As Long
Private Declare PtrSafe Function DragQueryFile Lib "shell32.dll" Alias "DragQueryFileA" ( ByVal HDROP As Long, ByVal UINT As Long, ByVal lpStr As String, ByVal ch As Long) As Long
Private Declare PtrSafe Function CloseClipboard Lib "user32" () As Long
Private Const CF_HDROP As Long = 15
Private Sub test_clipboard()
Dim nHandle As Long
If IsClipboardFormatAvailable(CF_HDROP) > 0 Then
If OpenClipboard(0) <> 0 Then
nHandle = GetClipboardData(CF_HDROP)
If nHandle <> 0 Then
' Query number of files in clipboard -> returns always 0
Debug.Print CStr(DragQueryFile(nHandle, GetNumOfFiles, vbNullString, 0))
End If
CloseClipboard
End If
End If
End sub
)。这样,如果网络打了几秒钟,你的套接字将需要更长的时间才能填满,然后阻止。
SO_SNDBUF