Ruby TCP套接字未读取完整输入数据。

huangapple go评论56阅读模式
英文:

Ruby TCP Socket does not read the entire input data

问题

I've translated the text you provided. Here it is:

我已经实现了一个简单的TCP服务器,监听特定的地址和端口:

TCPServer.open(address, port) do |server|
    file = File.open(file_name, "wb")
    while client = server.accept
        while buffer = client.gets()
            puts buffer
            file.write(buffer)
        end
    end
end

当我通过netcat发送短字符串或小于4096字节时,它完整地读取它们。当消息超过这个大小时,它被截断,甚至在连接关闭后和eof达到后仍然被截断。

我尝试实现了一个替代TCPServer的解决方案:

one_hundred_kb = 1024 * 100
Socket.tcp_server_loop(address, port) do |connection|
    begin
        file = File.open(file_name, "wb")
        # 以1百KB或更少的块读取数据。
        while data = connection.readpartial(one_hundred_kb) do
            puts data
            file.write(data)
        end
    rescue EOFError
        connection.close unless connect.nil?
    end
end

这个解决方案似乎也有与前一个相同的问题。我发现了一个类似的主题,可能会澄清这个问题,但我无法改变客户端发送消息到服务器的方式。

是否有办法改变最大读取大小,以及为什么数据会被截断而无法恢复?

编辑

正如@Stefan问我的,我通过发送一个非常大的字符串(大于4096字节,由一长串1组成,末尾带有两个xx)。在服务器端,最终的数据被截断,xx不会显示。

编辑2

通过分析由netcat直接生成的流量,使用tcpdump,我注意到实际上是netcat将最大长度限制为4096字节。因此,Socket和TCPServer类与生产客户端一起正常工作。导致我使用netcat来测试Socket类实现和EOF管理的差异(在上面的Socket类实现中正确管理)。这导致生成了一个损坏的二进制文件。

英文:

I've implemented a simple tcp server listening on a specific address and port:

TCPServer.open(address,port) do |server|
    file = File.open(file_name,"wb")
    while client = server.accept
        while buffer = client.gets()
            puts buffer
            file.write(buffer)
        end
    end
end

When through netcat I send short strings or under 4096 bytes it reads them entirely. When the message exceeds the size it is truncated, even after the connection and once the eof is reached.

I tried to implement an alternative to TCPServer:

one_hundred_kb = 1024 * 100
Socket.tcp_server_loop(address,port) do |connection|
begin
   file = File.open(file_name,"wb")
   # Read data in chunks of 1 hundred kb or less.
   while data = connection.readpartial(one_hundred_kb) do
       puts data
       file.write(data)
   end
   rescue EOFError
       connection.close unless connect.nil?
   end
end

This solution also seems to have the same problem as the previous one.
I found a similar thread
that might clarify the issue but but I can't change the way the client sends the messages to the server.

Is there a way to change the maximum read size and why the data is truncated and can't be recovered?

EDIT

As @Stefan asked me, I highlighted my problem by sending a very large string greater than 4096 bytes (composed of a very long sequence of 1s and with two trailing xxs). On the server side, the final data was truncated and the x's were not displayed.

EDIT 2

Analyzing the traffic generated directly by netcat with tcpdump, I noticed that it's actually netcat that cuts the maximum length to 4096 bytes.
So both the Socket and TCPServer classes work fine with the production client. The bug that led me to use netcat to test the differences between the class derived from the lack of management of the EOF (managed correctly in the case of the implementation with the Socket class above). This caused the generation of a corrupted binary.

答案1

得分: 1

你只是有错误的印象,文件被截断了,因为在关闭或刷新之前你查看了它的内容。

英文:

You just have the false impression that the file were truncated, since you look at its content before it has been closed or flushed.

huangapple
  • 本文由 发表于 2023年4月19日 16:56:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76052570.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定