当前位置: 首页 > 知识库问答 >
问题:

如何正确处理持久TCP套接字连接(以模拟HTTP服务器)?

娄弘
2023-03-14

所以,我尝试使用套接字和Ruby来模拟一些基本的HTTP持久性连接——用于大学课堂。

关键是构建一个服务器——能够处理多个客户端——接收文件路径并返回文件内容——就像HTTP GET一样。

当前服务器实现循环监听客户端,当有传入连接时触发新线程,并从该套接字读取文件路径。它非常笨,但是在处理非持久连接时工作良好——每个连接一个请求。

但它们应该坚持不懈。

这意味着客户端不必担心关闭连接。在非持久版本中,服务器响应响应并关闭连接-再见客户端,再见。但是持久性意味着服务器线程应该循环并等待更多的传入请求,直到。。。直到没有更多的要求。服务器如何知道这一点?没有!需要某种超时。我试着用Ruby的超时来做,但是没有成功。

谷歌搜索一些解决方案——除了被彻底建议避免使用超时模块之外——我已经看到很多关于IO的帖子。选择方法,它应该比使用线程和其他东西更好地处理这个套接字等待问题(考虑到Ruby线程(不)是如何工作的,这听起来很酷)。我在这里试图理解IO是如何做到的。select可以工作,但在当前场景中仍然无法使其工作。

所以我问了两件事:

>

  • 我如何在服务器端有效地处理这个超时问题,或者使用一些基于线程的解决方案、低级套接字选项或者一些IO. Select魔法?

    客户端如何知道服务器已关闭其连接端?

    下面是服务器的当前代码:

    require 'date'
    module Sockettp
      class Server
        def initialize(dir, port = Sockettp::DEFAULT_PORT)
          @dir = dir
          @port = port
        end
    
        def start
          puts "Starting Sockettp server..."
          puts "Serving #{@dir.yellow} on port #{@port.to_s.green}"
    
          Socket.tcp_server_loop(@port) do |socket, client_addrinfo|
            handle socket, client_addrinfo
          end
        end
    
        private
        def handle(socket, addrinfo)
          Thread.new(socket) do |client|
            log "New client connected"
            begin
              loop do
                if client.eof?
                  puts "#{'-' * 100} end connection"
                  break
                end
    
                input = client.gets.chomp
    
                body = content_for(input)
    
                response = {}
    
                if body
                  response.merge!({
                    status: 200,
                    body: body
                  })
                else
                  response.merge!({
                    status: 404,
                    body: Sockettp::STATUSES[404]
                  })
                end
    
                log "#{addrinfo.ip_address} #{input} -- #{response[:status]} #{Sockettp::STATUSES[response[:status]]}".send(response[:status] == 200 ? :green : :red)
    
                client.puts(response.to_json)
              end
            ensure
              socket.close
            end
          end
        end
    
        def content_for(path)
          path = File.join(@dir, path)
    
          return File.read(path) if File.file?(path)
          return Dir["#{path}/*"] if File.directory?(path)
        end
    
        def log(msg)
          puts "#{Thread.current} -- #{DateTime.now.to_s} -- #{msg}"
        end
      end
    end
    

    最新消息

    我能够使用IO模拟超时行为。选择方法,但当与两个线程结合以接受新连接和另一个线程处理请求时,实现感觉不太好。并发性使情况变得疯狂和不稳定,除非我能找到更好的方法来使用这个解决方案,否则我可能不会坚持下去。

    更新2

    似乎超时仍然是处理这个问题的最佳方式。我会坚持下去,直到找到更好的选择。我仍然不知道如何处理僵尸html" target="_blank">客户端连接。

    解决方案

    我最终使用了IO. Select(在查看werick代码时受到了启发)。你可以在这里检查最终版本(lib/超文本传输协议/服务器/client_handler.rb)

  • 共有1个答案

    包修贤
    2023-03-14

    您应该实现类似心跳数据包的功能。客户端应在几秒/分钟后向发送特殊数据包,以确保服务器不会超时客户端的连接。在这通电话里你什么都不做。

     类似资料:
    • 问题内容: 我正在尝试Go-并希望创建一个可以远程登录,发送命令和接收响应的TCP服务器。 上面的代码片段每次都会关闭连接,将我踢出终端会话。但是我真正想要的是能够保持连接打开以进行更多的I / O操作。如果我只是删除,则服务器似乎挂在某处,因为它不再获得任何响应。 我解决此问题的方法是让我的handleRequest方法无休止地循环,以便它在收到消息之前永远不会退出。这是否合适- 还是有更好的实

    • 我使用来管理服务器端的套接字连接。如果服务器(tomcat)关闭,我如何确保任何活动的套接字连接被正确终止? 有好心的听众吗?或任何可以防止服务器关闭的拦截器,例如,如果在关闭期间有任何打开的套接字,则最多60秒;但同时关闭套接字,在关机期间不接受任何连接?

    • 真的需要你帮忙。 我的项目是通过电缆连接两台PC机,并使用tcp套接字将客户端文本框形式的字符串发送到服务器。问题是ATI只能发送一个字符串,然后连接就会关闭。 注意:某个端口上的连接将在表单加载中建立并成功。

    • 问题内容: 我的Go服务器上有一个有效的TCP套接字设置。我接受传入连接,运行for循环并使用net.Conn.Read函数读取传入数据。 但这对我来说毫无意义。如何知道已收到完整的消息以便继续返回消息大小? 这是我目前的代码: 可以说我的应用程序发送的消息长度为6个字节(可以是任意大小)。怎么知道收到消息后才继续呢? 我的经验主要在于C#,所以Go在这里并不常见。对于我的C#应用​​程序,消息具

    • 问题内容: 假设我有一个Java程序,该程序使用HTTP 1.1在服务器上发出HTTP请求,并且不关闭连接。我提出一个请求,并读取从绑定到套接字的输入流返回的所有数据。但是,在发出第二个请求时,服务器没有响应(或者流有问题- 它不再提供任何输入)。如果我按顺序发出请求(请求,请求,读取),则可以正常工作,但(请求,读取,请求,读取)则不能。 有人能解释为什么会发生这种情况吗?(代码片段如下)。无论

    • 问题内容: 我想在我们的其中一台Web服务器上进行一些性能测试,以了解服务器如何处理大量持久连接。不幸的是,我对HTTP和Web测试不是很熟悉。这是到目前为止我已经获得的Python代码: 我的主要问题是: 如何保持这些连接的生命? 我设置了很长的超时时间,但这是一种非常粗糙的方法,我甚至不确定它是否会影响连接。是否只是偶尔偶尔请求一两个字节? (此外,与我代码末尾的丑陋块相比,还有一个更好的过程