jjzjj

sockets - 关闭套接字和关闭网络流之间的区别(System.Net.Sockets)

coder 2023-09-19 原文

我有一个代理服务器实现,如果我直接关闭套接字(System.Net.Sockets TCPClient.Client.Close())然后客户端收到连接中止错误,但如果我使用系统,则在向客户端发送最终响应后.Net.Sockets TCPClient.getStream().Close(),它成功运行。我想了解有什么区别以及为什么客户端在第一种情况下收到错误?

最佳答案

我想说,套接字的关闭并不是大多数人认为的微不足道的操作:) 首先,您应该了解应该如何正确完成关闭。基本上,您必须考虑到 close 是一种消息,就像从您的套接字发出的任何其他消息一样。或者换句话说 close() 是通信另一端的信息,表明对等方完成了某种工作。 现在重要的是要了解拥有一个 TCP 套接字,您可以通知对等方您已完成发送或完成监听。 在此页面上,您可以查看它在后台的工作方式(请注意,ACK 和 FIN 是 IP 层消息,因此即使使用普通套接字实现,您也永远看不到它们):http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm

所以现在是更实际的步骤。请考虑您有一个客户端和服务器。服务器需要接收消息并关闭连接。请考虑客户端只是要发送一条消息然后关闭连接。如果您还考虑到网络需要一些时间来处理您的通信,您会意识到如果您快速执行此操作,客户端将在服务器收到您的消息之前关闭连接。如果可以,TCPClient.Client.Close() 客户端将停止监听任何内容(这也意味着有关服务器关闭连接的信息)。所以 TCP 堆栈来玩(windows 为你做) - 如果你将以这种方式关闭套接字,TCP 堆栈需要通知服务器站点无论服务器已发送的任何内容都将转储。所以这就是你有异常(exception)的原因。

所以正确的做法是:

  1. 通知服务器客户端发送完任何数据(FIN)
  2. 等到服务器确认他知道客户端不会发送任何数据(ACK)
  3. 现在服务器应该通知客户端将停止发送数据(FIN)
  4. 现在客户可以说 - “好的,我明白了,我不会再听了”(ACK)

无论如何,C# TCPClient 似乎隐藏了后台套接字关闭例程的逻辑,但如果您不以正确的方式调用关闭序列,您最终会出错。

我希望这个有点长的解释能帮助你理解它在后台是如何工作的,并最终让你明白为什么。

如果您想了解更多信息,这也是阅读更多有关 TCP 协议(protocol)详细信息的好方法:http://www.tcpipguide.com/free/t_TCPIPTransmissionControlProtocolTCP.htm

关于sockets - 关闭套接字和关闭网络流之间的区别(System.Net.Sockets),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49828437/

有关sockets - 关闭套接字和关闭网络流之间的区别(System.Net.Sockets)的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  3. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  4. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用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

  5. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  6. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  7. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  8. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  9. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  10. ruby - 如何关闭 ruby​​ gem "Spreadsheet?"中的文件 - 2

    下面的代码在我第一次运行它时就可以正常工作:require'rubygems'require'spreadsheet'book=Spreadsheet.open'/Users/me/myruby/Mywks.xls'sheet=book.worksheet0row=sheet.row(1)putsrow[1]book.write'/Users/me/myruby/Mywks.xls'当我再次运行它时,我会收到更多消息,例如:/Library/Ruby/Gems/1.8/gems/spreadsheet-0.6.5.9/lib/spreadsheet/excel/reader.rb:11

随机推荐