2016-01-07 15 views
7

Nie jestem zbyt obeznany z Ruby, więc nie mogłem znaleźć dokumentacji dla tej metody.Co TCPSocket # każdy iterować w ruby?

Dzwoniąc każdy na obiekcie TCPSocket, jak to

require "socket" 

srv = TCPServer.new("localhost", 7887) 
skt = srv.accept 
skt.each {|arg| p arg} 

Czy blok uzyskać wywoływana raz na pakiet TCP, raz na linii (po każdym „\ n” char), raz na ciąg (po po każdy NUL/EOF) lub coś zupełnie innego?

Odpowiedz

5

TL; DR TCPSocket.each będzie iterować dla każdego nowego, rozdzielanego znakiem nowej linii \n, który otrzymuje.

Więcej szczegółów:

TCPSocket tylko BasicSocket z jakimś dodatkowym cukrem pudrem na wierzchu. A BasicSocket jest dzieckiem klasy IO. Klasa IO to tylko strumień danych; w związku z tym jest iterable. I that is where można znaleźć, jak each jest zdefiniowany dla TCPSocket.

Uruchom konsolę irb i wprowadź linię kodu z gniazdem $stdin, aby sprawdzić, jak zachowuje się each. Obaj dziedziczą po IO. Oto przykład tego, co się dzieje:

irb(main):011:0> $stdin.each {|arg| p arg + "."} 
hello 
"hello\n." 

Ale bezpośrednio odpowiedzieć na pytanie, blok jest wywoływana raz na \n charakteru. Jeśli twój klient wysyła dane po 1 znaku na raz, to blok nie zostanie wykonany, dopóki nie zobaczy \n.

Oto szybki klient próbka pokazać to:

irb(main):001:0> require 'socket' 
=> true 
irb(main):002:0> s = TCPSocket.open("localhost", 7887) 
=> #<TCPSocket:fd 9> 
irb(main):003:0> s.puts "hello" 
=> nil 
irb(main):007:0> s.write "hi" 
=> 2 
irb(main):008:0> s.write ", nice to meet you" 
=> 18 
irb(main):009:0> s.write "\n" 
=> 1 

A oto co serwer drukowane:

"hello\n" 
"hi, nice to meet you\n" # note: this did not print until I sent "\n" 
+1

Należy również pamiętać, że separator może być przekazany jako argument (np ' thing.each (sep = "\ r \ n") '), lub ustawić dla' IO # each' wraz z kilkoma innymi metodami, ustawiając '$ /', globalny domyślny separator, który, o ile nie zostanie zmieniony, domyślnie przyjmuje wartość '. \ n'. – Linuxios

+0

Świetna odpowiedź, ale jestem zdezorientowany ostatnim zdaniem: Jeśli wyślę 1 bajt/pakiet przez strumień TCP, to wejście będzie buforowane, dopóki bajt nie będzie "\ n" i tylko wtedy zostanie przekazane do bloku, prawda? – Benno

+0

To jest poprawne @Benno, dane wejściowe będą buforowane, dopóki bajt nie będzie "\ n'". ** Następnie ** zostanie wykonany blok 'each'. O ile nie zmienisz domyślnego zachowania, jak zauważyło Linuxios. –

Powiązane problemy