Danielle Adams / RailsConf 2017
@adamzdanielle
@danielleadams
DNS
IP
App Server
(ie. Puma)
Rack
Middleware
Rails
"The Transmission Control Protocol is intended for use as a highly reliable host-to-host protocol between hosts in packet-switched computer communication networks, and in interconnected systems of such networks."
RFC (1981)
Internet Protocol Suite
application layer
transport layer
internet layer
link layer
physical layer
"[...] the TCP provides a set of addresses or ports within each host. Concatenated with the network and host addresses from the internet communication layer, this forms a socket."
RFC (1981)
Server
(ie. Rails App)
Database
(ie. SQLite)
Client
(ie. Browser)
Server
(ie. Printer)
Client
???
require 'socket'
socket = TCPSocket.new '127.0.0.1', 8080
socket.write 'Hello, RailsConf!'
socket.close
# client.rb
Server
(ie. Rails App)
Database
(ie. SQLite)
Client
(ie. Browser)
Server
Client
loop do
client = server.accept
end
require 'socket'
server = TCPServer.new 8080
puts "There's a new client: #{client}"
puts client.read
# server.rb
client.close
Printer
Browser
???
Printer
Browser
Rails
Controller
Worker
app/
\_ controllers/
\_ labels_controller.rb
\_ workers/
\_ printer_worker.rb
config/
config.ru
db/
lib/
public/
tests/
# app/controllers/labels_controller.rb
def create
label = Label.create! label_params
PrinterWorker.perform_async label.zpl
end
# app/workers/printer_worker.rb
sidekiq_options queue: 'devices'
def perform(message)
socket = TCPSocket.new
socket.write message
socket.close
end
# app/controllers/labels_controller.rb
def create
label = Label.create! label_params
PrinterWorker.perform_async label.zpl
end
# app/workers/printer_worker.rb
sidekiq_options queue: 'devices'
def perform(message)
socket = TCPSocket.new
socket.write message
socket.close
end
???
Scanner
BAR CODE
Database
Daemon
Scanner
BAR CODE
Worker
Database
app/
\_ workers/
\_ scan_worker.rb
config/
config.ru
db/
lib/
\_ daemons/
\_ scan.rb
public/
tests/
# bin/scans
require_relative '../lib/daemons/scan'
Daemons::Scan.listen
# lib/daemons/scan.rb
require 'socket'
require 'sidekiq'
server = TCPServer.new port
client = server.accept
while message = client.gets
ScanWorker.perform_async(message)
end
client.close
# bin/scans
require_relative '../lib/daemons/scan'
Daemons::Scan.listen
# lib/daemons/scan.rb
require 'socket'
require 'sidekiq'
server = TCPServer.new
client = server.accept
while message = client.gets
ScanWorker.perform_async(message)
end
client.close
Zebra Programming Language is a label-definition and printer-control language.
^XA
^FO15,15^BQN,2,6^FDID-10^FS
^CF0,50
^FO150,30^FDHello, my name is:^FS
^CF0,120
^FO150,90^FDDanielle^FS
^CF0,50
^FO150,200^FDTitle: Software Engineer^FS
^XZ
\x04252017
\x1FRA:1L:Sx:00:C0:NF
\x1F0340\r\n
obstacles
Not all hardware supports connections to multiple sockets. Some only support one at a time.
A framework may not support persistent open sockets.
Not all hosting services support the level of privacy that may be needed for a device that is online.
Integration with hardware becomes difficult to mock and requires lots of manual testing.
@adamzdanielle
@danielleadams
github.com/danielleadams/web-box-demo
slides.com/danielleadams/outside-the-web-box