ZetCode

Ruby Socket

last modified October 18, 2026

In this article we show how to do Ruby network programming with sockets. Socket programming is low-level. The goal of this tutorial is to introduce network programming including these low-level details.

In programming, a socket is an endpoint of a communication between two programs running on a network. Sockets are used to create a connection between a client program and a server program.

Ruby's socket module provides an interface to the Berkeley sockets API.

Note: In networking, the term socket has a different meaning. It is used for the combination of an IP address and a port number.

Network protocols

TCP/IP is a suite of protocols used by devices to communicate over the Internet and most local networks. TCP is more reliable, has extensive error checking, and requires more resources. It is used by services such as HTTP, SMTP, or FTP. UDP is much less reliable, has limited error checking, and requires less resources. It is used by services such as VoIP.

The Socket::SOCK_STREAM is used to create a socket for TCP and Socket::SOCK_DGRAM for UDP.

Address families

When we create a socket, we have to specify its address family. Then we can only use addresses of that type with the socket.

For the AF_INET address family, a pair (host, port) is specified. The host is a string representing either a hostname in Internet domain notation like example.com or an IPv4 address like 93.184.216.34, and port is an integer.

Ruby Socket.getnameinfo

The Socket.getnameinfo method obtains information about a socket address.

get_addr.rb
#!/usr/bin/ruby

require 'socket'

p Socket.getnameinfo Socket.sockaddr_in 80, "127.0.0.1"
p Socket.getnameinfo ["AF_INET", 80, "localhost"]

The example resolves the loopback address 127.0.0.1 and the name localhost to node names and service names. Using the loopback address keeps the example independent of network access and DNS.

require 'socket'

The Ruby socket API is in the socket module.

p Socket.getnameinfo Socket.sockaddr_in 80, "127.0.0.1"
p Socket.getnameinfo ["AF_INET", 80, "localhost"]

A socket address is created either with Socket.sockaddr_in or with an array containing the address family, port, and host name. To resolve a public host such as example.com, pass that name in the same way; the result depends on DNS and network access.

$ ./get_addr.rb
["localhost", "http"]
["localhost", "http"]

Socket.getifaddrs & Socket.ip_address_list

The Socket.getifaddrs returns an array of interface addresses and the Socket.ip_address_list returns local IP addresses as an array.

get_locals.rb
#!/usr/bin/ruby

require 'socket'

pp Socket.getifaddrs

p '----------------------------'

pp Socket.ip_address_list

The example prints all local interfaces and IP addresses.

Ruby UDP socket example

UDP is a communication protocol that transmits independent packets over the network with no guarantee of arrival and no guarantee of the order of delivery. One service that used UDP is echo.

The Echo Protocol is a service in the Internet Protocol Suite defined in RFC 862. The Echo Protocol can use the TCP or the UDP on the port number 7. The server sends back an identical copy of the data it received.

$ cat /etc/services | grep echo | head -4
echo            7/tcp
echo            7/udp
echo            4/ddp                   # AppleTalk Echo Protocol

Port 7 is reserved for echo service.

Due to security concerns, the echo service is disabled in most cases. Instead, we use the small Ruby echo server shown in the client/server example below. Start it in one terminal:

$ ./echo_server.rb 
starting echo server

Then run the client in another terminal. It connects to localhost on port 4444.

echo_client.rb
#!/usr/bin/ruby

require 'socket'

host = 'localhost'
port = 4444

msg =  ARGV[0] || "hello"

s = UDPSocket.new
s.connect host, port

s.sendmsg msg + "\n"
puts s.recv 20

s.close

The example sends a small message to the echo service. The message is echoed back.

s = UDPSocket.new

A new UDP socket is created with UDPSocket.new.

s.connect host, port

We connect to the host on the specified port.

s.sendmsg msg + "\n"

We send the message to the echo service with the sendmsg method.

puts s.recv 20

The recv method receives a message; its argument is maxlen, which is the maximum number of bytes to receive.

s.close

We close the socket with close.

$ ./echo_client.rb
hello
$ ./echo_client.rb cau
cau

Our messages are echoed back to us. You can watch the UDP traffic with the tcpdump tool if you need to inspect the packets.

Ruby TCP socket example

TCP provides reliable, ordered, and error-checked delivery of a stream of octets (bytes) between applications running on hosts communicating via an IP network.

$ cat /etc/services | grep qotd
qotd            17/tcp          quote

Port 17 is reserved for the quote of the day service.

A quote of the day service is a useful debugging and measurement tool. The service simply sends a short message without regard to the input.

qotd_client.rb
#!/usr/bin/ruby

require 'socket'

s = TCPSocket.new 'djxmmx.net', 17
s.send '', 0

puts s.recv(350).delete("\0")
s.close

The example creates a client program that connects to a QOTD service.

s = TCPSocket.new 'djxmmx.net', 17

A TCP/IP socket is created with TCPSocket.new. We provide a hostname and the port number.

s.send '', 0

We send an empty message to the socket.

puts s.recv(350).delete("\0")
s.close

We receive the output, remove the trailing null byte, and close the socket.

$ ./qotd_client.rb 
"Oh the nerves, the nerves; the mysteries of this machine called man!
 Oh the little that unhinges it, poor creatures that we are!"
 Charles Dickens (1812-70)

The quote changes every day.

Ruby Socket HTTP HEAD request

A HEAD request is an HTTP GET request without a message body. The header of a request/response contains metadata, such as HTTP protocol version or content type.

http_head.rb
#!/usr/bin/ruby

require 'socket'

s = TCPSocket.new 'example.com', 80

s.write "HEAD / HTTP/1.0\r\n"
s.write "Host: example.com\r\n"
s.write "User-Agent: Console Http Client\r\n"
s.write "Accept: text/html\r\n"
s.write "Accept-Language: en-US\r\n"
s.write "Connection: close\r\n\r\n"

res = s.read
puts res

s.close

In the example, we send a HEAD request to example.com.

s.write "HEAD / HTTP/1.0\r\n"
s.write "Host: example.com\r\n"
s.write "User-Agent: Console Http Client\r\n"
s.write "Accept: text/html\r\n"
s.write "Accept-Language: en-US\r\n"
s.write "Connection: close\r\n\r\n"

A HEAD request is issued with the HEAD command followed by the resource URL and HTTP protocol version. Note that the \r\n are a mandatory part of the communication process. The details are described in RFC 9110.

$ ./http_head.rb 
HTTP/1.1 200 OK
Date: Sun, 18 Oct 2026 10:10:50 GMT
Content-Type: text/html; charset=utf-8
Connection: close
Server: cloudflare
Last-Modified: Tue, 13 Oct 2026 20:08:28 GMT
Allow: GET, HEAD
Accept-Ranges: bytes
Age: 8644
cf-cache-status: HIT
CF-RAY: a4c6c16709676e91-BTS
alt-svc: h3=":443"; ma=86400

Ruby Socket GET request

The HTTP GET method requests a representation of the specified resource. Requests using GET should only retrieve data.

http_get.rb
#!/usr/bin/ruby

require 'socket'

s = TCPSocket.new 'example.com', 80
s.write "GET / HTTP/1.0\r\n"
s.write "Host: example.com\r\n"
s.write "Connection: close\r\n\r\n"

res = s.read
puts res

s.close

The example reads the home page of example.com using a GET request.

s.write "GET / HTTP/1.0\r\n"
s.write "Host: example.com\r\n"
s.write "Connection: close\r\n\r\n"

We write a simple GET request to the socket. The Host header is required by many servers.

$ ./http_get.rb 
HTTP/1.1 200 OK
Date: Sun, 18 Oct 2026 10:15:48 GMT
Content-Type: text/html; charset=utf-8
Connection: close
Server: cloudflare
Last-Modified: Tue, 13 Oct 2026 20:08:28 GMT
Allow: GET, HEAD
Accept-Ranges: bytes
Age: 8943
cf-cache-status: HIT
CF-RAY: a4c6c8b2acd6c258-BTS
alt-svc: h3=":443"; ma=86400

<!doctype html><html lang=en><head><meta charset=utf-8><link rel=icon href=data:,><meta name=viewport content="width=device-width,initial-scale=1"><title>Example Domain</title><style>html{color-scheme:light dark;background:light-dark(#eee,#222)}body{font:16px/1.6 system-ui,sans-serif;max-width:26em;margin:auto;padding:25vh 2em 2em;text-align:center}</style></head><body><p>This domain is for use in documentation examples without needing permission. This is not a service; avoid relying on it for testing and monitoring purposes.</p><script src=/s.js></script></body></html>

Ruby client/server example

In the following section, we create a UDP echo client and server.

echo_server.rb
#!/usr/bin/ruby

require 'socket'

puts 'starting echo server'

Socket.udp_server_loop 4444 do |data, src|
    src.reply data
end

The echo server is created with Socket.udp_server_loop. It creates a UDP/IP server on the given port and calls the block for each message received. The server sends the message back to the client.

udp_client.rb
#!/usr/bin/ruby

require 'socket'

s = UDPSocket.new

s.connect 'localhost', 4444
s.send "hello", 0

puts s.recv 50
s.close

The client sends a message to the echo server.

Ruby socket simple web server

The following example creates a simple web server.

web_server.rb
#!/usr/bin/ruby

require 'socket'

port = (ARGV[0] || 8080).to_i

server = TCPServer.new port

p server
puts "server started on port #{port}"

loop do 

  client = server.accept
  puts "Request: #{client.gets}"
  client.print "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"
  client.print "<html><body><h1>#{Time.now}</h1></body></html>\r\n"
  client.close
end

The server sends the current time in the HTML output. The accept method accepts an incoming connection. It returns a new TCPSocket object.

$ ./web_server.rb 
#<TCPServer:fd 5, AF_INET, 0.0.0.0, 8080>
server started on port 8080

We start the server.

$ nc localhost 8080
GET /

HTTP/1.1 200 OK
Content-Type: text/html

<html><body><h1>2026-10-18 12:10:58 +0200</h1></body></html>

We test the server with the nc tool.

In this article we have shown how to create simple networking programs with sockets in Ruby.

List all Ruby tutorials.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.