Web basics: a TCP Server in Ruby

Web basics: a TCP Server in Ruby

This series guide covers the very basics of Web and the building blocks of a Web server.

If you have ever wondered on how a Web server works and have a basic knowledge of Ruby, this guide is for you.

Essentially, the main elementary units of a web server are:

  • Client-server architecture model
  • TCP - Transmission Control Protocol
  • HTTP - Hypertext Transfer Protocol
  • HTML/CSS/Javascript

Client-server model

Client-server model is a networking structure that allows different devices connecting to each other over a computer network, being local or public (Internet).

Consider two different devices connected to a network:

  • the client (web browser) requests a webpage to the server
  • the server (another computer in the network) that serves the requested webpage to the client

Alt Text

In order to establish a client-server connection, it's essential to indicate some kind of "agreement" among devices. Such agreement holds information like devices location, message being sent and so on.

This is the communication protocol, composed by layers ranging from physical material up to application traits.

We won't dig further into all layers but focus only on layers that contain TCP and HTTP. The following image illustrates the communication layers and its protocols:

Alt Text

TCP

Transmission Control Protocol is one of the main transport protocols in the OSI model. It embraces reliability and is responsible to deliver a message from one point to another.

In each device, we have to open endpoints that will be used by the TCP to send and receive data. A single computer can open and close thousands of endpoints. Those endpoints are called Sockets.

In Ruby we can implement a TCP client-server by using the package socket which is included in the standard library.

TCP Client

Let's create a TCP client using test/unit, which means: the test will be the client.

tcp_test.rb

require 'socket'
require 'test/unit'

class ServerTest< Test::Unit::TestCase
  def test_tcp_request_response
    server = TCPSocket.open('localhost', 4242)

    request = 'Hello, server!'
    server.puts(request)

    response = server.gets
    assert_equal "Hey, client!\n", response

    server.close
  end
end
  • the test takes into account that we have opened a socket server in the port 4242
  • localhost refers to the same local machine, but it could be any valid location address in the internet
  • the test (client) sends a request message to the server
  • the test (client) reads the response message from the server
  • the test (client) closes the socket connection to the server

If we try to run the test (ruby tcp_test.rb), we'll get the following error:

SocketError: getaddrinfo: Name or service not known

Which means there's no opened socket server in the port 4242 of localhost. Let's make the test pass.

TCP Server

tcp_server.rb

require 'socket'            

socket = TCPServer.new(4242)

client = socket.accept      
request = client.gets       

response = 'Hey, client!'       
client.puts(response)       

client.close                
socket.close
  • server creates a new socket in the port 4242
  • server accepts connections to the socket and waits for a new connection to come in
  • when a new client connection arrives, server reads the request message from the client
  • server sends a response message to the client
  • server closes the connection with client
  • server closes the socket and terminates itself

Because the server must run in a separate process, we have to first:

  • start the server, ruby tcp_server.rb
  • open a new tab or window, and run ruby tcp_test.rb

Expectation: the test should pass and the server should terminate.

1 tests, 1 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed

Wrapping Up

This post was the first part of series and an introduction to the client-server model along with building a simple TCP server in Ruby with TDD.

In the upcoming posts we'll learn about HTTP.

 
Share this