我正在使用TCPListener使用VB.NET创建语音服务器。为了检查传入连接,我在Form Load方法中创建了一个无限循环,并且只要有连接,它就会接受它,然后创建一个新线程来处理通信。以下是代码:
Private WithEvents SR As New SoundRecorder
Private TCPListener As TcpListener
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
TCPListener = New TcpListener(Net.IPAddress.Parse(GetIPv4Address), 2021)
TCPListener.Start()
While 1
If TCPListener.Pending = True Then
Dim voiceCom As New BroadcastSound(TCPListener.AcceptSocket())
Dim th As New Threading.Thread(AddressOf voiceCom.startCommunication)
th.Start()
End If
Application.DoEvents()
End While
End Sub
服务器运行良好并且尊重所有连接但问题是处理器使用率总是100%因为此服务器是否连接了任何客户端。有没有更好的方法来监听传入连接?
答案 0 :(得分:1)
每当你发现自己达到Application.DoEvents
时,你应该尝试重新考虑 - 这通常是一种解决方法。至少这次你已经知道你处境不好:)
如果您愿意同步执行所有操作,我会启动一个新主题,然后在其中调用TcpListener.AcceptTcpClient
。 (如果你真的想要套接字,你可以调用TcpListener.AcceptSocket
,但TcpClient
通常是一种更简单的方法。)该调用将阻塞,直到客户端准备就绪,所以你不需要循环检查Pending
属性。
因此,您的UI线程已准备好接收UI事件,并且一个线程正在等待入站请求。
现在,你可以使用异步API - 特别是如果你使用VB11,使用Async和Await。你可以使用:
Dim client As TcpClient = Await listener.AcceptTcpClientAsync();
...在UI线程中。这不会阻止UI线程,但会异步启动接受传入连接。建立连接后,其余的异步方法将继续。你不需要额外的线程。您可以在UI线程上执行 all 您的工作,使用异步来避免阻塞。这样可以更容易地与UI进行交互,但需要一些时间来习惯。
如果你对异步和网络都不熟悉,我可能会用同步版本启动 ...这样你就可以更少了。然后,如果您以后有冒险精神,可以将所有内容转换为异步方法。
答案 1 :(得分:0)
我意识到这已经很老了,但在我搜索类似的东西时,这是最初的结果之一。
Public Class main
Private client As TcpClient
Private listener As TcpListener
Private WithEvents tcpBg As BackgroundWorker
Private Sub main_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
tcpBg = New BackgroundWorker
'Requires a routine that cancels background worker.
tcpBg.WorkerSupportsCancellation = True
'ip is most likely from a Textbox.
Dim adr As Net.IPAddress = Net.IPAddress.Parse(ip)
listener = New TcpListener(adr, 60000)
tcpBg.RunWorkerAsync()
End Sub
Private Sub tcpBg_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles tcpBg.DoWork
listener.Start()
While tcpBg.CancellationPending = False
client = listener.AcceptTcpClient
'Do something with your client.
client.Close()
End While
End Sub
End Class
这就是我实现TCPListener的方法。我的FX-8350使用率约为0.1%。我不能肯定地说我的Athlon II X2是什么样的,但它不可能超过百分之几。 GUI不会冻结,你不应该有任何真正的CPU使用。
当然,我的实际实现是在几个不同的类中。这是基础的一个简单例子。