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"
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
Ś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
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. –