vkill'blog

“技术本身没有太多价值,掌握了新的思考方式才是真的收获”

transfer file use socket

16:56 , vkill
很简陋的代码,只是为了实现
服务端

#test_s.rb
require 'TransferFile.rb'
require 'socket'

s = TCPServer.new(1088)
while true
  sock = s.accept()
  Thread.new() {
    printf "%s already conn!\n", sock
    begin
      tf = TransferFile.new()
      tf.file_client(sock,"./temp/")
      tf.incept
    rescue
      p $!
    end
    printf "%s close!\n", sock
  }
end

客户端

#test_c.rb
require 'TransferFile.rb'
require 'socket'

socket = TCPSocket.new('127.0.0.1', 1088)
file = "11.exe"
p file
begin
  tf = TransferFile.new()
  tf.file_server(socket, file)
  tf.send
rescue
  p $!
end


TransferFile.rb

#
#TransferFile.rb
#

require 'timeout'
class TFSSocketWriteError < StandardError
end
class TFSReadFileInfoError < StandardError
end
class TFCSocketReadError < StandardError
end
class TFCReadHeaderError < StandardError
end
class TFCWriteFileError < StandardError
end

class TransferFile
  def initialize
    @socket = nil
    @file = nil
    @send_header = ''
    @call_header = {}
    @read_once_size = defined?(READ_ONCE_SIZE) ? READ_ONCE_SIZE : 102400
    @transfer_size = 0
    @sleep_sec = 0.05
    @sock_write_timeout_sec = 30
    @sock_read_timeout_sec = 30
  end

  #server
  def file_server(socket, file)
    @socket = socket
    @file = file
    begin
      @file_name = File.basename(@file)
      @file_size = File.size(@file)
      @file_mtime = File.mtime(@file)
    rescue
      raise TFSReadFileInfoError, format("read file info Err [%s]", $!)
    end
  end
  def defined_send_header_file()
    @send_header.concat(format("file-name: %s\r\n", @file_name))
    @send_header.concat(format("file-size: %s\r\n", @file_size))
    @send_header.concat(format("file-mtime: %s\r\n", @file_mtime))
    if @send_header.length < 1024
      @send_header.concat(" " * (1024 - @send_header.length))
    end
  end
  def send()
    #new thread sending
    sending = Thread.new() {
      defined_send_header_file()
      sock_write @send_header
      ###send for bytes
      #File.open(@file, "rb") do |f|
      #  @send_ok = false
      #  while not f.eof?
      #    sock_write f.read(@read_once_size)
      #    @transfer_size += @read_once_size
      #  end
      #end
      ###send for line
      @send_ok = false
      File.open(@file, "rb").each_line do |line|
        sock_write line
        @transfer_size += line.length
      end
      @send_ok = true
    }
    while true
      while not defined?(@send_ok)
        printf "\rtransfering initialize ..."
        sleep @sleep_sec
      end
      printf "\rtransfering[%s:%sbytes] %s%%", @file_name, @file_size, @transfer_size * 100 / (@file_size + 1)
      unless sending.status
        if @send_ok
          printf "\rtransfering[%s:%sbytes] 100%%", @file_name, @file_size
          printf " OK\n"
          return true
        else
          printf " ERR\n"
          return false
        end
      end
      sleep @sleep_sec
    end
  end
  def sock_write(data='')
    #p data
    begin
      timeout(@sock_write_timeout_sec) {@socket.write(data)}
    rescue
      raise TFSSocketWriteError, format("send data Err [%s]", $!)
    rescue TimeoutError
      raise TFSSocketWriteError, "timeout"
    end
  end

  #client
  def file_client(socket, dir='.')
    @socket = socket
    @dir = dir
  end
  def defined_file_info()
    resp = sock_readpartial(1024)
    raise TFCReadHeaderError, "read header Err" unless resp.length == 1024 and resp.count("\r\n")
    resp.each_line do |line|
      if line =~ /^(.*)+:[ ]?(.*)+$/
        @call_header[$1.strip] = $2.strip
      end
    end
    @file_name = @call_header["file-name"] || nil
    @file_size = @call_header["file-size"].to_i || nil
    raise TFCReadHeaderError, "defined file-name Err" unless @file_name
    raise TFCReadHeaderError, "defined file-size Err" unless @file_size
  end
  def incept()
    #new thread calling
    calling = Thread.new() {
      defined_file_info()
      begin
        f = File.new(@dir + '/' + @file_name, "wb+")
      rescue
        raise TFCWriteFileError, format("create file Err [%s]", $!)
      end
      @transfer_ok = false
      while true
        resp = sock_readpartial @read_once_size
        break if resp.empty?
        f.write resp
        f.flush
        @transfer_size = File.size(f)
      end
      if File.size(f) == @file_size
        f.close
        @transfer_ok = true
      else
        File.delete(f)
      end
    }
    while true
      while not defined?(@transfer_ok)
        printf "\rtransfering initialize ..."
        sleep @sleep_sec
      end
      printf "\rtransfering[%s:%sbytes] %s%%", @file_name, @file_size, @transfer_size * 100 / (@file_size + 1)
      unless calling.status
        if @transfer_ok
          printf "\rtransfering[%s:%sbytes] 100%%", @file_name, @file_size
          printf " OK\n"
          return true
        else
          printf " ERR\n"
          return false
        end
      end
      sleep @sleep_sec
    end
  end

  def sock_readpartial(len=1024)
    begin
      if @socket.eof?
        ''
      else
        resp = timeout(@sock_read_timeout_sec) {@socket.readpartial(len)}
        resp
      end
    rescue
      raise TFCSocketReadError, format("incept data Err [%s]", $!)
    end
  end
end

Last modified by vkill on2009/08/07 16:57
类别:ruby & rails | Tags: , , , , , , , | 0 条评论, 962 次阅读
网友评论(0):
发表评论:

Nickname: 
Email:
Site URI: