Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TCP Socket programming in Ruby

TCP Socket programming in Ruby

As software developers, a lot of the time we’re building applications that rely on some sort of network connection. Due to Ruby’s great abstractions we take most of the network related stuff for granted. We think we know how all of that works, but do we? Let’s go over the fundamentals together, learn about how Ruby models TCP Sockets and how we can make a good use of it.

Presented at: WindyCityRails 2016

92d08794b535e41a4082c57ea547546e?s=128

Sebastian Sogamoso

September 16, 2016
Tweet

Transcript

  1. TCP Socket Programming in Ruby

  2. My name is Sebastián Sogamoso Tweet to me @sebasoga

  3. Why?

  4. None
  5. None
  6. API

  7. API REST

  8. REST JSON API

  9. REST JSON XML API

  10. API REST JSON SOAP XML

  11. API REST WSDL JSON SOAP XML

  12. None
  13. None
  14. None
  15. None
  16. Line protocol

  17. “CONTROLLER_V":4-5:,"SOFTWARE_V":1-1\n set engine "on"=true,"rpm"=100 1434055562000000000 set led "on"=true,"color"="green" 1434055562000010000\n\n

  18. What is a Socket?

  19. Endpoints of a bidirectional communication channel

  20. Sockets speak to other sockets using standard Unix file descriptors

  21. None
  22. “Everything (in Unix) is a file”

  23. Yes, sockets act like files

  24. The end @sebasoga

  25. None
  26. None
  27. None
  28. TCP Sockets programming in Ruby?

  29. None
  30. None
  31. C programs for which Ruby has bindings

  32. Create an endpoint for communication Prepare a socket for incoming

    connections Assign a socket to an address socket(2) listen(2) bind(2)
  33. Connect to a socket in the given address Send a

    stream to the connected socket Manage new incoming connections connect(2) write(2) accept(2)
  34. Receive socket’s incoming stream End connection with peer socket Perform

    synchronous I/O multiplexing read(2) close(2) select(2)
  35. None
  36. None
  37. None
  38. None
  39. Berkley Socket API

  40. Client / Server Lifecycle

  41. Server

  42. socket(2) Server

  43. Server bind(2) socket(2) 127.0.0.1:3000

  44. bind(2) socket(2) 127.0.0.1:3000 Server

  45. bind(2) socket(2) 127.0.0.1:3000 Server

  46. listen(2) bind(2) socket(2) Server

  47. listen(2) bind(2) socket(2) Client Server

  48. socket(2) listen(2) bind(2) socket(2) Client Server

  49. socket(2) connect(2) listen(2) bind(2) socket(2) Client Server

  50. socket(2) connect(2) listen(2) bind(2) socket(2) Client Server

  51. socket(2) connect(2) accept(2) listen(2) bind(2) socket(2) Client Server

  52. socket(2) connect(2) accept(2) listen(2) bind(2) socket(2) Client Server

  53. socket(2) connect(2) accept(2) listen(2) bind(2) socket(2) Client Server

  54. Client socket(2) connect(2) accept(2) listen(2) bind(2) socket(2) SYN Server

  55. Client socket(2) connect(2) accept(2) listen(2) bind(2) socket(2) SYN ACK Server

  56. Client socket(2) connect(2) accept(2) listen(2) bind(2) socket(2) SYN ACK ACK

    Server
  57. Client socket(2) connect(2) write(2) accept(2) listen(2) bind(2) socket(2) Server

  58. Client socket(2) connect(2) write(2) read(2) accept(2) listen(2) bind(2) socket(2) Server

  59. Client socket(2) connect(2) write(2) read(2) accept(2) listen(2) bind(2) socket(2) Request

    is processed Server
  60. Client socket(2) connect(2) write(2) read(2) accept(2) listen(2) bind(2) socket(2) write(2)

    Server
  61. Client socket(2) connect(2) write(2) read(2) accept(2) listen(2) bind(2) socket(2) write(2)

    Server
  62. Client socket(2) connect(2) write(2) read(2) accept(2) listen(2) bind(2) socket(2) write(2)

    read(2) Server
  63. Client socket(2) connect(2) write(2) read(2) write(2) read(2) accept(2) listen(2) bind(2)

    socket(2) Server
  64. Client socket(2) connect(2) write(2) read(2) write(2) read(2) accept(2) listen(2) bind(2)

    socket(2) close(2) Server
  65. Client socket(2) connect(2) write(2) read(2) close(2) write(2) read(2) accept(2) listen(2)

    bind(2) socket(2) Server
  66. Client socket(2) connect(2) write(2) read(2) close(2) write(2) read(2) accept(2) listen(2)

    bind(2) socket(2) close(2) Server
  67. This is how those system calls look like in Ruby

  68. The server

  69. require ‘socket'

  70. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM, 0)
  71. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM, 0) Domain
  72. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, _, _)
  73. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INETv6, _, _)
  74. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:UNIX, _, _)
  75. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM, 0) Type
  76. require ‘socket' # Create a new TCP socket socket =

    Socket.new(_, :STREAM, _)
  77. require ‘socket' # Create a new TCP socket socket =

    Socket.new(_, :DRAM, _)
  78. require ‘socket' # Create a new TCP socket socket =

    Socket.new(_, :RAW, _)
  79. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM, 0) Protocol
  80. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM)
  81. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM)
  82. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM) # Create a C struct to hold the address for listening address = Socket.pack_sockaddr_in(5000,‘127.0.0.1’) socket.bind(address)
  83. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM) # Create a C struct to hold the address for listening address = Socket.pack_sockaddr_in(5000,‘127.0.0.1’) socket.bind(address) # Start listening for incoming connections socket.listen(5) client.close
  84. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM) # Create a C struct to hold the address for listening address = Socket.pack_sockaddr_in(5000,‘127.0.0.1’) socket.bind(address) # Start listening for incoming connections socket.listen(5) client.close
  85. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM) # Create a C struct to hold the address for listening address = Socket.pack_sockaddr_in(5000,‘127.0.0.1’) socket.bind(address) # Start listening for incoming connections socket.listen(Socket::SOMAXCONN) client.close
  86. require ‘socket' # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM) # Create a C struct to hold the address for listening address = Socket.pack_sockaddr_in(5000,‘127.0.0.1’) socket.bind(address) # Start listening for incoming connections socket.listen(Socket::SOMAXCONN) client.close
  87. require ‘socket' Socket.tcp_server_loop(5000) do |socket, client_addrinfo| begin socket.listen(Socket::SOMAXCONN) ensure c.close

    end end
  88. The client

  89. require ‘socket’ # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM) address = Socket.pack_sockaddr_in(5000,’127.0.0.1’) # Use connect to get the server client.connect(address) client.close
  90. require ‘socket’ # Create a new TCP socket socket =

    Socket.new(:INET, :STREAM) address = Socket.pack_sockaddr_in(5000,’127.0.0.1’) # Use connect to get the server client.connect(address) client.close
  91. require ‘socket’ Socket.tcp(‘127.0.0.1’, 5000) do |socket| begin ensure socket.close end

    end # or socket = TCPSocket.new(‘127.0.0.1’, 5000)
  92. Socket I/O

  93. require 'socket' module WCR class Server def start @server =

    ::TCPServer.new(port) ::Socket.accept_loop(@server) do |socket| # Read from the connection until EOF request = socket.read # Process the request response = process(request) # Write back the result of the hash operation socket.write(response) socket.close end end end
  94. require 'socket' module WCR class Server def start server =

    ::TCPServer.new(port) ::Socket.accept_loop(server) do |socket| # Read from the connection until EOF request = socket.read # Process the request response = process(request) # Write back the result of the hash operation socket.write(response) socket.close end end end
  95. require 'socket' module WCR class Server def start server =

    ::TCPServer.new(port) ::Socket.accept_loop(server) do |socket| # Read from the connection until EOF request = socket.read # Process the request response = process(request) # Write back the result of the hash operation socket.write(response) socket.close end end end
  96. require 'socket' module WCR class Server def start server =

    ::TCPServer.new(port) ::Socket.accept_loop(server) do |socket| # Read from the connection until EOF request = socket.read # Process the request response = process(request) # Write back the result of the hash operation socket.write(response) socket.close end end end
  97. require 'socket' module WCR class Server def start server =

    ::TCPServer.new(port) ::Socket.accept_loop(server) do |socket| # Read from the connection until EOF request = socket.read # Process the request response = process(request) # Write back the result of the hash operation socket.write(response) socket.close end end end
  98. require 'socket' module WCR class Server def start server =

    ::TCPServer.new(port) ::Socket.accept_loop(server) do |socket| # Read from the connection until EOF request = socket.read # Process the request response = process(request) # Write back the result of the hash operation socket.write(response) socket.close end end end
  99. require 'socket' module WCR class Server def start server =

    ::TCPServer.new(port) ::Socket.accept_loop(server) do |socket| # Read from the connection until EOF request = socket.read # Process the request response = process(request) # Write back the result of the hash operation socket.write(response) socket.close end end end
  100. require 'socket' module WCR class Client atrr_accessor :host, :port def

    request(string) # Create a new connection for each operation socket = ::TCPSocket.new(host, port) socket.write(string) # Send EOF after writing the request socket.close_write # Read until EOF to get the response socket.read end end end
  101. require 'socket' module WCR class Client atrr_accessor :host, :port def

    request(string) # Create a new connection for each operation socket = ::TCPSocket.new(host, port) socket.write(string) # Send EOF after writing the request socket.close_write # Read until EOF to get the response socket.read end end end
  102. require 'socket' module WCR class Client atrr_accessor :host, :port def

    request(string) # Create a new connection for each operation socket = ::TCPSocket.new(host, port) socket.write(string) # Send EOF after writing the request socket.close_write # Read until EOF to get the response socket.read end end end
  103. require 'socket' module WCR class Client atrr_accessor :host, :port def

    request(string) # Create a new connection for each operation socket = ::TCPSocket.new(host, port) socket.write(string) # Send EOF after writing the request socket.close_write # Read until EOF to get the response socket.read end end end
  104. require 'socket' module WCR class Client atrr_accessor :host, :port def

    request(string) # Create a new connection for each operation socket = ::TCPSocket.new(host, port) socket.write(string) # Send EOF after writing the request socket.close_write # Read until EOF to get the response socket.read end end end
  105. What’s next?

  106. • Buffering • Non blocking I/O • Multiplexing connections •

    Timeouts • Network architecture patterns
  107. Interested?

  108. None
  109. sourcediving.com @sebasoga

  110. Thanks!