Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does TCPSocket#each iterate over in ruby?

Tags:

ruby

I'm not too familiar with Ruby, so I wasn't able to find the documentation for this method.

When calling each on a TCPSocket object, like this

require "socket"

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

Does the block get called once per tcp packet, once per line (after each '\n' char), once per string (after after each NUL/EOF), or something different entirely?

like image 379
Benno Avatar asked Jan 07 '16 17:01

Benno


1 Answers

TL;DR TCPSocket.each will iterate for each newline delimited \n string it receives.

More details:

A TCPSocket is just a BasicSocket with some extra powder sugar on top. And a BasicSocket is a child of IO class. The IO class is just a stream of data; thus, it is iterable. And that is where you can find how each is defined for TCPSocket.

Fire up an irb console and enter your line of code with the $stdin socket to see how each behaves. They both inherit from IO. Here is an example of what happens:

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

But to directly answer the question, the block is called once per \n character. If your client is sending data 1 character at a time then the block is not going to be executed until it sees the \n.

Here is a quick sample client to show this:

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

And here is what the server printed out:

"hello\n"
"hi, nice to meet you\n" # note: this did not print until I sent "\n"
like image 137
Mike S Avatar answered Oct 13 '22 16:10

Mike S