29 September 2013

tcp sockets

by mo


Sockets use IP addresses to route messages to specific hots. A host is identified by a unique IP address. DSN maps host names to IP address. When you ask DNS to resolve a host name it responds with an IP address.


IP addresses don’t always refer to remote hosts. Sometimes you want to connect to your local host. Most loopback interfaces are a virtual interface, unlike the interface to your network card. With a loopback address your network is constrained to the local host.

localhost is the name of the loopback interface and the IP is usually This is defined in /etc/hosts.


The combination of IP address and port number must be unique for each socket. You could have a socket with an IPv4 address listening on the same port as a socket with an IPv6 address. You cannot have two sockets with the same IPv4 address listening on the same port number.

The following is an example of the different kinds of sockets you can create. :INET implies and IPv4 address.

require 'socket'
Socket.new(:INET, :STREAM) # TCP socket
Socket.new(:INET, :DGRAM)  # UDP socket
Socket.new(:UNIX, :STREAM) # UNIX stream socket
Socket.new(:UNIX, :DGRAM)  # UNIX datagram socket


In order to create a connection you must have two sockets.

  1. initiator (client)
  2. listener (server)

A socket that listens is a server. A socket that initiates a connection is a client.

Server Lifecyle

  1. create
  2. bind
  3. listen
  4. accept
  5. close
require 'socket'

# create
server = Socket.new(:INET, :STREAM)
# bind
server.bind(Socket.pack_sockaddr_in(4481, ''))
# listen with listen queue of 128 connections

loop do
  # accept
  connection, _ = server.accept
  # close

Another way to write the above is like this:

require 'socket'

Socket.tcp_server_loop(4481) do |connection|

Client Lifecyle

  1. create
  2. bind
  3. connect
  4. close
require 'socket'

# create
socket = Socket.new(:INET, :STREAM)
# bind to port in ephemeral range and connect
socket.connect(Socket.pack_sockaddr_in(80, 'google.com'))
# close

An alternative way to write this is:

require 'socket'

Socket.tcp('google.com', 80) do |connection|
  connection.write "GET / HTTP/1.1\r\n"
unix 💎