Рубиновый TFTP сервер - PullRequest
5 голосов
/ 18 мая 2011

У меня есть следующий код, который я собрал для простого TFTP-сервера Ruby. Он работает нормально, так как он слушает порт 69, и мой TFTP-клиент подключается к нему, и я могу записывать пакеты в test.txt, но вместо того, чтобы просто записывать пакеты, я хочу иметь возможность TFTP-файл от моего клиента в каталог / temp.

Заранее спасибо за помощь!

require 'socket.so'

class TFTPServer
  def initialize(port)
    @port = port
  end

  def start
    @socket = UDPSocket.new
    @socket.bind('', @port)
    while true
      packet = @socket.recvfrom(1024)
      puts packet

      File.open('/temp/test.txt', 'w') do |p|
            p.puts packet   
        end 
    end
  end
end

server = TFTPServer.new(69)
server.start

Ответы [ 2 ]

7 голосов
/ 20 мая 2011

Вместо записи в /temp/test.txt вы можете использовать Tempfile класса ruby's * ruby's

Так в вашем примере:

require 'socket.so'
require 'tempfile'

class TFTPServer
  def initialize(port)
   @port = port
  end

  def start
    @socket = UDPSocket.new
    @socket.bind('', @port)
    while true
      packet = @socket.recvfrom(1024)
      puts packet

      Tempfile.new('tftpserver') do |p|
        p.puts process_packet( packet )
      end 
    end
  end
end

server = TFTPServer.new(69)
server.start

Это создастгарантированный уникальный временный файл в вашем каталоге / tmp с именем, основанным на 'tftpserver'.

РЕДАКТИРОВАТЬ: я заметил, что вы хотите написать в / temp (не / tmp), чтобы сделать это, вы можете сделать Tempfile.new('tftpserver', '/temp'), чтобы указать конкретный временный каталог.

Редактировать 2: Для всех, кто заинтересованесть библиотека, которая сделает это https://github.com/spiceworks/net-tftp

5 голосов
/ 22 мая 2011

вы не получите это так легко, протокол tftp относительно прост, но команда put / get не без сохранения состояния, или, по крайней мере, если файл не помещается в один пакет, это что-то вроде 512, но некоторые расширения разрешить больший пакет

файл на проводе разделен, и вы получите последовательность пакетов каждый пакет имеет порядковый номер, поэтому другой конец может отправить ошибку для определенного пакета

Вы должны взглянуть на страницу википедии:

http://en.wikipedia.org/wiki/Trivial_File_Transfer_Protocol

вот пример кода, который я написал в 2005 году, но id делает зеркальное отражение (отправляет файл) это питон, но достаточно похож на ruby: D

def send_file(self, addr, filesend, filesize, blocksize):
    print '[send_file] Sending %s (size: %d - blksize: %d) to %s:%d' % (filesend, filesize, blocksize, addr[0], addr[1])
    fd = open(filesend, 'rb')

    for c in range(1, (filesize / blocksize) + 2):
        hdr = pack('!H', DATA) + pack('!H', c)
        indata = fd.read(blocksize)
        if debug > 5: print '[send_file] [%s] Sending block %d size %d' % (filesend, c, len(indata))
        self.s.sendto(hdr + indata, addr)
        data, addr = self.s.recvfrom(1024)
        res = unpack('!H', data[:2])[0]
        data = data[2:]
        if res != ACK:
            print '[send_file] Transfer aborted: %s' % errors[res]
            break
        if debug > 5:
            print '[send_file] [%s] Received ack for block %d' % (filesend, unpack('>H', data[:2])[0] + 1)
    fd.close()

    ## End Transfer
    pkt = pack('!H', DATA) + pack('>H', c) + NULL
    self.s.sendto(pkt, addr)
    if debug: print '[send_file] File send Done (%d)' % c

вы можете найти константы в arpa / tftp.h (вам нужен Unix или поиск в Интернете)

порядковый номер - это формат с прямым порядком байтов (сетевой порядок)! H для struct pack ruby имеет что-то вроде структуры python в классе String

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...