我有一个使用 TCPListener 和异步方法 BeginAcceptTCPClient 的 TCP 服务器:
Imports System.Net.Sockets
Imports System.Threading
Imports System.Net
Public Class TCPServer
Private mPort As Integer
Public Event IncomingMessage(ByVal Message As String, ByVal IP As String)
'This signals threadpool threads to stop...
Private mStopServer As ManualResetEvent
Private mListener As TcpListener
Public Sub New(ByVal Port As Integer)
mPort = Port
Start()
End Sub
Public Sub Start()
Try
If mListener Is Nothing Then
mListener = New TcpListener(IPAddress.Any, mPort)
End If
mListener.Start()
AcceptClients()
mStopServer = New ManualResetEvent(False)
Catch ex As Exception
ExceptionHandling.LogError(ex)
End Try
End Sub
Private Sub AcceptClients()
Try
Dim result As IAsyncResult = mListener.BeginAcceptTcpClient(AddressOf HandleAsyncConnection, mListener)
Catch ex As Exception
ExceptionHandling.LogError(ex)
End Try
End Sub
Dim so As New Object
Public Sub StopListening()
Try
mStopServer.Set()
mListener.Stop()
Catch ex As Exception
ExceptionHandling.LogError(ex)
End Try
End Sub
Private Sub HandleAsyncConnection(ByVal result As IAsyncResult)
Try
If Not mStopServer.WaitOne(0) Then
Dim listener As TcpListener = DirectCast(result.AsyncState, TcpListener)
If listener Is Nothing Then Exit Sub
Dim client As TcpClient = listener.EndAcceptTcpClient(result)
Trace.WriteLine("Connected to new client")
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ProcessClient), client)
AcceptClients()
End If
Catch ex As Exception
ExceptionHandling.LogError(ex)
End Try
End Sub
Private Sub ProcessClient(ByVal client As Object)
Dim newClient As TcpClient = DirectCast(client, TcpClient)
Try
' Buffer for reading data
Dim bytes As Byte() = New Byte(32 * 1024) {}
Dim clientData As New System.Text.StringBuilder()
Using ns As NetworkStream = newClient.GetStream()
' set initial read timeout to 1 minute to allow for connection
ns.ReadTimeout = 60000
' Loop to receive all the data sent by the client.
Dim bytesRead As Integer = 0
Do
' read the data
Try
If mStopServer.WaitOne(0) Then Exit Sub
bytesRead = ns.Read(bytes, 0, bytes.Length)
If bytesRead > 0 Then
clientData.Append(System.Text.Encoding.UTF8.GetString(bytes, 0, bytesRead))
' decrease read timeout to 1 second now that data is coming in
ns.ReadTimeout = 1000
End If
Catch ioe As IO.IOException
Trace.WriteLine(ioe.ToString)
bytesRead = 0
Dim bError() As Byte = Error400()
ns.Write(bError, 0, bError.Length)
End Try
Loop While ns.DataAvailable
ForwardData(clientData.ToString, newClient.Client.RemoteEndPoint.ToString)
'Trace.Write(clientData.ToString())
'Acknowledge success
bytes = Ack200()
ns.Write(bytes, 0, bytes.Length)
End Using
Catch ex As Exception
ExceptionHandling.LogError(ex)
Finally
' stop talking to client
If newClient IsNot Nothing Then
newClient.Close()
End If
End Try
End Sub
Private Sub ForwardData(ByVal Data As String, ByVal IP As String)
RaiseEvent IncomingMessage(Data, IP)
End Sub
Public Function Ack200() As Byte()
Return System.Text.Encoding.UTF8.GetBytes("Okay")
End Function
Public Function Error400() As Byte()
Return System.Text.Encoding.UTF8.GetBytes("Error")
End Function
End Class
我的问题是,我偶尔会在 HandleAsyncConnection 方法中遇到异常: “现有连接被远程主机强行关闭”就在 EndAcceptTCPClient 方法中。此时,TCPListener 似乎停止了监听。问题是我无法轻松地对此进行测试,因为它只发生在远程测试 VM 上,并且每 24 小时左右才发生一次。如果我知道如何用测试客户端重现错误,我就能解决这个问题。 Wireshark 显示在异常发生时发送了一个重置 [RST] 数据包。所以我要么需要知道如何处理异常,要么需要知道如何使用测试客户端重现问题。
最佳答案
您可以通过重新启动服务器或退回您所连接的服务来重现该问题。基本上,任何终止与您通信的进程的行为都会产生此错误。
要处理,您几乎只需要捕获异常并尝试重新连接到服务器,可能需要等到它再次可用。
编辑:
您的代码停止监听,因为您对 AcceptClients 的调用是在异常发生之后,因此您永远不会返回到 BeginAcceptTCPClient 函数。另外,我不确定这如何与异步调用一起工作,但对我来说它看起来像是无限递归。 BeginAcceptTCP 客户端调用 HandlAsynConnection 的委托(delegate),后者调用 AcceptClients,从而开始循环。在我看来,经过如此多的连接后,您应该会收到堆栈溢出错误。您可以在 HandleAsyncConnection 中的 try block 中添加一个 finally 子句并在那里调用它,因此在发生错误时它总是被调用。
Try
If Not mStopServer.WaitOne(0) Then
Dim listener As TcpListener = DirectCast(result.AsyncState, TcpListener)
If listener Is Nothing Then Exit Sub
Dim client As TcpClient = listener.EndAcceptTcpClient(result)
Trace.WriteLine("Connected to new client")
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ProcessClient), client)
End If
Catch ex As Exception
ExceptionHandling.LogError(ex)
Finally
AcceptClients()
End Try
关于vb.net - 如何处理TCPListener "An existing connection was forcibly closed by the remote host",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6958958/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub