Ruby Socket Programming
Socket programming is the foundation of network programming, allowing programs to communicate with other programs over the network. Ruby provides a powerful Socket library that makes network programming simple and intuitive. Whether creating servers or clients, Ruby can handle it with ease. This chapter will explain in detail Socket programming in Ruby, including TCP, UDP communication, and HTTP client implementation.
🎯 Socket Basics
What is a Socket
A Socket is an abstract concept in network programming. It is the endpoint of network communication. Through Sockets, applications can send and receive data over the network. Socket provides a standard communication mechanism, allowing programs on different hosts to communicate with each other.
Socket Types
- Stream Socket (SOCK_STREAM): Uses TCP protocol, providing reliable, connection-oriented communication
- Datagram Socket (SOCK_DGRAM): Uses UDP protocol, providing connectionless communication
- Raw Socket (SOCK_RAW): Provides direct access to underlying protocols
Socket Addressing
Sockets identify an endpoint on the network through IP address and port number:
- IP Address: Identifies the host on the network (e.g., 192.168.1.100)
- Port Number: Identifies a specific service on the host (e.g., 80, 443, 3000)
🔌 TCP Socket Programming
TCP Client
TCP (Transmission Control Protocol) is a connection-oriented protocol that provides reliable data transmission.
require 'socket'
# Create TCP client
def tcp_client(server_host, server_port, message)
# Create TCP Socket
socket = Socket.new(:INET, :STREAM)
# Connect to server
sockaddr = Socket.sockaddr_in(server_port, server_host)
socket.connect(sockaddr)
# Send message
socket.write(message)
puts "Sent: #{message}"
# Receive response
response = socket.read(1024)
puts "Received response: #{response}"
# Close connection
socket.close
end
# Usage example (requires running server first)
# tcp_client('localhost', 3000, "Hello, Server!")
# Simpler approach
def simple_tcp_client(server_host, server_port, message)
socket = TCPSocket.new(server_host, server_port)
socket.puts message
response = socket.gets
puts "Server response: #{response}"
socket.close
end
# simple_tcp_client('localhost', 3000, "Hello, Server!")TCP Server
require 'socket'
# Create TCP server
def tcp_server(port)
# Create server Socket
server = TCPServer.new(port)
puts "TCP server started, listening on port #{port}"
loop do
# Wait for client connection
client = server.accept
puts "Client connected: #{client.peeraddr[2]}:#{client.peeraddr[1]}"
# Create new thread to handle client
Thread.new(client) do |client_socket|
begin
# Read client message
while message = client_socket.gets
puts "Received message: #{message.chomp}"
# Reply to client
response = "Server received: #{message}"
client_socket.puts response
# Disconnect if quit command received
break if message.chomp == 'quit'
end
rescue => e
puts "Client processing error: #{e.message}"
ensure
client_socket.close
puts "Client connection closed"
end
end
end
end
# Start server (run in separate terminal)
# tcp_server(3000)
# More complete TCP server example
class TCPServerExample
def initialize(port)
@port = port
@server = nil
@clients = []
end
def start
@server = TCPServer.new(@port)
puts "Server started, listening on port #{@port}"
# Handle interrupt signals
trap('INT') { shutdown }
loop do
client = @server.accept
@clients << client
puts "New client connected: #{client.peeraddr[2]}:#{client.peeraddr[1]}"
# Create handling thread for each client
handle_client(client)
end
end
private
def handle_client(client)
Thread.new do
begin
client.puts "Welcome! Enter 'quit' to exit."
while message = client.gets
message = message.chomp
puts "Received message: #{message} (from #{client.peeraddr[2]})"
case message
when 'quit'
client.puts "Goodbye!"
break
when 'time'
client.puts "Current time: #{Time.now}"
when 'clients'
client.puts "Current connections: #{@clients.length}"
else
client.puts "Server reply: #{message}"
end
end
rescue => e
puts "Client error: #{e.message}"
ensure
@clients.delete(client)
client.close
puts "Client disconnected"
end
end
end
def shutdown
puts "Shutting down server..."
@server.close if @server
@clients.each(&:close)
exit
end
end
# Usage example
# server = TCPServerExample.new(3001)
# server.start📨 UDP Socket Programming
UDP Client
UDP (User Datagram Protocol) is a connectionless protocol that doesn't guarantee data transmission reliability but is faster.
require 'socket'
# UDP client
def udp_client(server_host, server_port, message)
# Create UDP Socket
socket = UDPSocket.new
# Send message to server
socket.send(message, 0, server_host, server_port)
puts "Sent: #{message}"
# Receive response
response, sender = socket.recvfrom(1024)
puts "Received response: #{response} (from #{sender[2]}:#{sender[1]})"
# Close Socket
socket.close
end
# Usage example (requires running UDP server first)
# udp_client('localhost', 3002, "UDP message test")UDP Server
require 'socket'
# UDP server
def udp_server(port)
# Create UDP Socket
socket = UDPSocket.new
socket.bind('localhost', port)
puts "UDP server started, listening on port #{port}"
loop do
# Receive message
message, sender = socket.recvfrom(1024)
puts "Received message: #{message} (from #{sender[2]}:#{sender[1]})"
# Send response
response = "Server received: #{message}"
socket.send(response, 0, sender[2], sender[1])
end
end
# Start UDP server (run in separate terminal)
# udp_server(3002)
# More complete UDP server example
class UDPServerExample
def initialize(port)
@port = port
@socket = nil
end
def start
@socket = UDPSocket.new
@socket.bind('0.0.0.0', @port)
puts "UDP server started, listening on port #{@port}"
# Handle interrupt signals
trap('INT') { shutdown }
loop do
message, sender = @socket.recvfrom(1024)
handle_message(message, sender)
end
end
private
def handle_message(message, sender)
client_ip, client_port = sender[2], sender[1]
puts "Received message: #{message.chomp} (from #{client_ip}:#{client_port})"
response = case message.chomp
when 'time'
Time.now.to_s
when 'ping'
'pong'
else
"Server received: #{message}"
end
@socket.send(response, 0, client_ip, client_port)
end
def shutdown
puts "Shutting down UDP server..."
@socket.close if @socket
exit
end
end
# Usage example
# server = UDPServerExample.new(3003)
# server.start🌐 HTTP Client
Basic HTTP Requests
require 'socket'
# Simple HTTP GET request
def simple_http_get(host, port = 80, path = '/')
# Create TCP connection
socket = TCPSocket.new(host, port)
# Send HTTP request
request = "GET #{path} HTTP/1.1\r\n"
request += "Host: #{host}\r\n"
request += "Connection: close\r\n"
request += "\r\n"
socket.write(request)
# Receive response
response = socket.read
socket.close
# Parse response
headers, body = response.split("\r\n\r\n", 2)
{ headers: headers, body: body, status: headers[/HTTP\/[\d\.]+\s+(\d+)/, 1] }
end
# Usage example
# result = simple_http_get('example.com', 80, '/')
# puts result[:body]HTTP POST Request
require 'socket'
require 'uri'
def http_post(host, port, path, data)
socket = TCPSocket.new(host, port)
body = URI.encode_www_form(data)
request = "POST #{path} HTTP/1.1\r\n"
request += "Host: #{host}\r\n"
request += "Content-Type: application/x-www-form-urlencoded\r\n"
request += "Content-Length: #{body.length}\r\n"
request += "Connection: close\r\n"
request += "\r\n"
request += body
socket.write(request)
response = socket.read
socket.close
puts response
end
# Usage example
# http_post('example.com', 80, '/submit', { name: 'John', age: 30 })Using Net::HTTP (Recommended)
require 'net/http'
require 'uri'
# HTTP GET request
def http_get(url)
uri = URI.parse(url)
response = Net::HTTP.get_response(uri)
{
status: response.code,
body: response.body,
headers: response.to_hash
}
end
# HTTP POST request
def http_post(url, data)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == 'https')
request = Net::HTTP::Post.new(uri.path)
request.set_form_data(data)
response = http.request(request)
{
status: response.code,
body: response.body
}
end
# Usage examples
# get_result = http_get('https://api.example.com/data')
# post_result = http_post('https://api.example.com/submit', { name: 'John' })📚 Next Steps
After mastering Ruby Socket programming, we recommend continuing to learn:
- Ruby Sending Email - SMTP - Learn email sending
- Ruby Web Services - Learn web service development
- Ruby Multithreading - Master concurrent programming
Continue your Ruby learning journey!