How to process telnet data(binary)

Hi everyone,

I’m using Net::telnet(windows) to get files from a linux system:

data = socket.cmd(“gzip -c xxx”)
f = File.open(“abc.gz”, “wb”)
f.write data
f.close
system(‘winrar … abc’)

but this code works only for some files, other file reported an CRC
error when being unzipped.
To solve the problem, I type “gzip -c xxx >abc1.gz” and download abc1.gz
through ftp(binary mode) and compare it with abc.gz, and found they
actually have differences, some bytes are not the same. I guess it’s
because the telnet protocol transfer some bytes before send it to me?

Please help me to work it out, Thanks a lot:)

On Wednesday, 28 March 2012 07:52:38 UTC-7, Fengfeng Li wrote:

Hi everyone,

I’m using Net::telnet(windows) to get files from a linux system:

[…]

Would you put a link to more complete source?
https://gist.github.com/

thanks,

Thufir

Have you tried setting Binmode option to Net::Telnet?

# Binmode:: if false (the default), newline substitution is 

performed.
# Outgoing LF is
# converted to CRLF, and incoming CRLF is converted to LF.
If
# true, this substitution is not performed. This value
can
# also be set with the #binmode() method. The
# outgoing conversion only applies to the #puts() and
#print()
# methods, not the #write() method. The precise nature of
# the newline conversion is also affected by the telnet
options
# SGA and BIN.

However I would say that your proposed way of doing things is very
fragile, because if nothing else there will be trailing garbage (the
command prompt) added to your data.

You might want to look at SCP or SFTP for a more robust way of copying
files from a Linux system.

THUFIR H. wrote in post #1053832:

On Wednesday, 28 March 2012 07:52:38 UTC-7, Fengfeng Li wrote:

Hi everyone,

I’m using Net::telnet(windows) to get files from a linux system:

[…]

Would you put a link to more complete source?
https://gist.github.com/

thanks,

Thufir

I haven’t finished it yet, becuase the problem still exists.

Brian C. wrote in post #1053836:

Have you tried setting Binmode option to Net::Telnet?

# Binmode:: if false (the default), newline substitution is

performed.
# Outgoing LF is
# converted to CRLF, and incoming CRLF is converted to LF.
If
# true, this substitution is not performed. This value
can
# also be set with the #binmode() method. The
# outgoing conversion only applies to the #puts() and
#print()
# methods, not the #write() method. The precise nature of
# the newline conversion is also affected by the telnet
options
# SGA and BIN.

However I would say that your proposed way of doing things is very
fragile, because if nothing else there will be trailing garbage (the
command prompt) added to your data.

You might want to look at SCP or SFTP for a more robust way of copying
files from a Linux system.

Thanks for your reply:)
I’ve already gsub the prompt. I tried Binmode true, the result is it
will change \n to \r\n, besides, same problem exist. For example, “\xFF”
is changed into “\xFF\xFF”.

I will look into SCP/SFTP and see if there’s a better way.

Brian C. wrote in post #1053836:

Have you tried setting Binmode option to Net::Telnet?

# Binmode:: if false (the default), newline substitution is

performed.
# Outgoing LF is
# converted to CRLF, and incoming CRLF is converted to LF.
If
# true, this substitution is not performed. This value
can
# also be set with the #binmode() method. The
# outgoing conversion only applies to the #puts() and
#print()
# methods, not the #write() method. The precise nature of
# the newline conversion is also affected by the telnet
options
# SGA and BIN.

However I would say that your proposed way of doing things is very
fragile, because if nothing else there will be trailing garbage (the
command prompt) added to your data.

You might want to look at SCP or SFTP for a more robust way of copying
files from a Linux system.

SCP seems only work between two linuxes, so I tried SFTP, it’s really
good. But some of my test machines(LINUX) don’t provide SSH service, so
I go back to the old way for them.
How can I solve the problem? Tt really bothers me, I’ve tried for 2 days
and cann’t finger out how telnet transfer its data.

Can anyone give me more clues? Thanks a lot.

On Thu, 29 Mar 2012 23:55:16 +0900, Fengfeng Li wrote:

Would you put a link to more complete source? https://gist.github.com/
[…]
I haven’t finished it yet, becuase the problem still exists.

While I may not be able to help, more information surely couldn’t hurt.
My suggestion was to post the code which you have – no worries.

-Thufir

THUFIR H. wrote in post #1054221:

On Thu, 29 Mar 2012 23:55:16 +0900, Fengfeng Li wrote:

Would you put a link to more complete source? https://gist.github.com/
[…]
I haven’t finished it yet, becuase the problem still exists.

While I may not be able to help, more information surely couldn’t hurt.
My suggestion was to post the code which you have – no worries.

-Thufir

I cann’t open https://gist.github.com/ on my work PC, so I post it
below, a little long. Plaese help me with it. Thanks. PS. @m_session is
a Net::Telnet object

#-------------------------
#This is the main code
#-------------------------
fc = linux_send(“String” => “gzip -c #{file_name}”)

if fc =~ /\x1f\x8b/
debugOut “download #{file_name} by telnet…”
fc.gsub!(“\xff\xff\xfa”, “\xff\xfa”)
fc = CDS::unzip_stream(@m_fileCache.getCachePath(), file_name, fc)
end

#-------------------------
#These are correlative methods
#-------------------------
module CDS

def self.writeFile(file_path, file_content) #ok
    fh = File.open(file_path, "wb")
    fh.write file_content
    fh.close
end

def self.unzip_file(path1, path2)
     org_path = Dir.pwd
    cache_path = File.dirname(path1)
    Dir.chdir(cache_path)

    cmd = "#{$winrar} e -ibck -inul -o+ #{path1.gsub('/', '\\')}"
     ret_code = system(cmd)

    fc = ""
    if File.exist?(path2)
        fc = readFile(path2).to_s
        begin
        File.delete(path2)
       rescue Exception
       end
    end

    begin
        File.delete(path1)
    rescue Exception
    end

    #恢复工作目录
    Dir.chdir(org_path)

    return fc
end

#解压缩 zip 文件流
def self.unzip_stream(cache_path, file_name, zip_content)
    #保存为临时文件
    path1 = getAFreeName(File.join(cache_path, "tmp_file"))
    writeFile(path1, zip_content)
    #解压临时文件,读取内容
    path2 = File.join(cache_path, File.split(file_name)[-1])
    fc = unzip_file(path1, path2)

    return fc
end

end

def linux_send(args)
    #参数处理
    if args.is_a?(Hash)
        cmd = args["String"]
        timeout = args["Timeout"] || 30
        prompt = args["Match"] || args["Prompt"]
    elsif args.is_a?(String)
        cmd = args
        timeout = 30
    end
    show_live(cmd)
    #如果出现timeout错误,反复尝试几次
    retry_time = 5
    begin
        #如果连接已建立,则每次都取当前提示符和当前目录
        @m_curr_prompt, @m_curr_pwd = "", ""
        if @m_session_login
            get_pwd()
        end

        debugOut ">>>write_session: #{cmd}"

        response_msg = ""
        #指定的提示符会被使用;没指定时如果不是cd命令且已知上一次提示符,使用上一次的;否则使用默认的
        if prompt

debugOut " waiting for match(#{prompt})"

            response_msg = @m_session.cmd("String" => cmd, "Timeout" 

=> timeout, “Match” => prompt)
elsif @m_curr_prompt.any? && cmd.strip !~ /^cd\s/i

debugOut " waiting for match(#{@m_curr_prompt})"

            response_msg = @m_session.cmd("String" => cmd, "Timeout" 

=> timeout, “Match” => Regexp.new(@m_curr_prompt.gsub(“[”,
“\[”).gsub(“]”, “\]”)) )
else

debugOut " waiting for match(#{@m_session.m_prompt})"

            response_msg = @m_session.cmd("String" => cmd, "Timeout" 

=> timeout)
end

    rescue TimeoutError => msg
        debugOut "#{msg}, try again!!!"
        debugOut ""
        retry_time -= 1
        retry if retry_time >= 0
    end
    #将回显中的当前提示符替换为空
    response_msg.gsub!(@m_curr_prompt, "") if @m_curr_prompt.any?

    return response_msg
end