Ruby - การเขียนโปรแกรมซ็อกเก็ต

Ruby ให้การเข้าถึงบริการเครือข่ายสองระดับ ในระดับต่ำคุณสามารถเข้าถึงการสนับสนุนซ็อกเก็ตพื้นฐานในระบบปฏิบัติการพื้นฐานซึ่งช่วยให้คุณใช้งานไคลเอนต์และเซิร์ฟเวอร์สำหรับทั้งโปรโตคอลที่เน้นการเชื่อมต่อและไม่มีการเชื่อมต่อ

Ruby ยังมีไลบรารีที่ให้การเข้าถึงระดับที่สูงขึ้นไปยังโปรโตคอลเครือข่ายระดับแอปพลิเคชันเฉพาะเช่น FTP, HTTP และอื่น ๆ

บทนี้จะช่วยให้คุณเข้าใจแนวคิดที่มีชื่อเสียงที่สุดในระบบเครือข่าย - การเขียนโปรแกรมซ็อกเก็ต

ซ็อกเก็ตคืออะไร?

ซ็อกเก็ตเป็นจุดสิ้นสุดของช่องทางการสื่อสารแบบสองทิศทาง ซ็อกเก็ตอาจสื่อสารภายในกระบวนการระหว่างกระบวนการบนเครื่องเดียวกันหรือระหว่างกระบวนการในทวีปต่างๆ

อาจนำซ็อกเก็ตไปใช้กับแชนเนลประเภทต่างๆ: ซ็อกเก็ตโดเมน Unix, TCP, UDP และอื่น ๆ ซ็อกเก็ตให้เรียนที่เฉพาะเจาะจงสำหรับการจัดการระบบขนส่งทั่วไปเช่นเดียวกับอินเตอร์เฟซสำหรับการจัดการทั่วไปส่วนที่เหลือ

Sockets มีคำศัพท์ของตัวเอง -

ซีเนียร์ ข้อกำหนดและคำอธิบาย
1

domain

ตระกูลของโปรโตคอลที่จะใช้เป็นกลไกการขนส่ง ค่าเหล่านี้เป็นค่าคงที่เช่น PF_INET, PF_UNIX, PF_X25 เป็นต้น

2

type

ประเภทของการสื่อสารระหว่างปลายทางทั้งสองโดยทั่วไปคือ SOCK_STREAM สำหรับโปรโตคอลที่เน้นการเชื่อมต่อและ SOCK_DGRAM สำหรับโปรโตคอลที่ไม่มีการเชื่อมต่อ

3

protocol

โดยทั่วไปเป็นศูนย์อาจใช้เพื่อระบุรูปแบบของโปรโตคอลภายในโดเมนและประเภท

4

hostname

ตัวระบุของอินเทอร์เฟซเครือข่าย -

สตริงซึ่งอาจเป็นชื่อโฮสต์ที่อยู่แบบจุด - รูปสี่เหลี่ยมหรือที่อยู่ IPV6 ในสัญกรณ์โคลอน (และอาจเป็นจุด)

สตริง "<broadcast>" ซึ่งระบุที่อยู่ INADDR_BROADCAST

สตริงที่มีความยาวเป็นศูนย์ซึ่งระบุ INADDR_ANY หรือ

จำนวนเต็มตีความเป็นที่อยู่ไบนารีในลำดับไบต์ของโฮสต์

5

port

เซิร์ฟเวอร์แต่ละตัวจะรับฟังไคลเอ็นต์ที่เรียกใช้พอร์ตอย่างน้อยหนึ่งพอร์ต พอร์ตอาจเป็นหมายเลขพอร์ต Fixnum สตริงที่มีหมายเลขพอร์ตหรือชื่อของบริการ

ลูกค้าธรรมดา

ในที่นี้เราจะเขียนโปรแกรมไคลเอนต์ที่เรียบง่ายซึ่งจะเปิดการเชื่อมต่อไปยังพอร์ตที่กำหนดและโฮสต์ที่กำหนด คลาส RubyTCPSocketให้ฟังก์ชันเปิดเพื่อเปิดซ็อกเก็ตดังกล่าว

TCPSocket.open(hosname, port )เปิดเชื่อมต่อ TCP ชื่อโฮสต์บนพอร์ต

เมื่อคุณเปิดซ็อกเก็ตแล้วคุณสามารถอ่านได้เหมือนกับอ็อบเจ็กต์ IO ใด ๆ เมื่อเสร็จแล้วอย่าลืมปิดเช่นเดียวกับที่คุณปิดไฟล์

รหัสต่อไปนี้เป็นไคลเอนต์ที่เรียบง่ายมากที่เชื่อมต่อกับโฮสต์และพอร์ตที่กำหนดอ่านข้อมูลที่มีอยู่จากซ็อกเก็ตจากนั้นออก -

require 'socket'        # Sockets are in standard library

hostname = 'localhost'
port = 2000

s = TCPSocket.open(hostname, port)

while line = s.gets     # Read lines from the socket
   puts line.chop       # And print with platform line terminator
end
s.close                 # Close the socket when done

เซิร์ฟเวอร์ที่เรียบง่าย

ในการเขียนอินเทอร์เน็ตเซิร์ฟเวอร์เราใช้ไฟล์ TCPServerชั้นเรียน อ็อบเจ็กต์ TCPServer เป็นโรงงานสำหรับอ็อบเจ็กต์ TCPSocket

ตอนนี้โทร TCPServer.open(hostname, portเพื่อระบุพอร์ตสำหรับบริการของคุณและสร้างไฟล์TCPServer วัตถุ.

จากนั้นเรียกใช้วิธีการยอมรับของวัตถุ TCPServer ที่ส่งคืน วิธีนี้จะรอจนกว่าไคลเอ็นต์จะเชื่อมต่อกับพอร์ตที่คุณระบุแล้วส่งคืนอ็อบเจ็กต์TCPSocketที่แสดงถึงการเชื่อมต่อกับไคลเอ็นต์นั้น

require 'socket'                 # Get sockets from stdlib

server = TCPServer.open(2000)    # Socket to listen on port 2000
loop {                           # Servers run forever
   client = server.accept        # Wait for a client to connect
   client.puts(Time.now.ctime)   # Send the time to the client
   client.puts "Closing the connection. Bye!"
   client.close                  # Disconnect from the client
}

ตอนนี้เรียกใช้เซิร์ฟเวอร์นี้ในพื้นหลังจากนั้นเรียกใช้ไคลเอนต์ด้านบนเพื่อดูผลลัพธ์

เซิร์ฟเวอร์ TCP หลายไคลเอ็นต์

เซิร์ฟเวอร์ส่วนใหญ่บนอินเทอร์เน็ตได้รับการออกแบบมาเพื่อจัดการกับลูกค้าจำนวนมากในคราวเดียว

คลาสเธรดของรูบี้ทำให้การสร้างเซิร์ฟเวอร์มัลติเธรดเป็นเรื่องง่ายหนึ่งที่ยอมรับคำขอและสร้างเธรดการดำเนินการใหม่ทันทีเพื่อประมวลผลการเชื่อมต่อในขณะที่อนุญาตให้โปรแกรมหลักรอการเชื่อมต่อเพิ่มเติม -

require 'socket'                 # Get sockets from stdlib

server = TCPServer.open(2000)    # Socket to listen on port 2000
loop {                           # Servers run forever
   Thread.start(server.accept) do |client|
   client.puts(Time.now.ctime)   # Send the time to the client
   client.puts "Closing the connection. Bye!"
   client.close                  # Disconnect from the client
   end
}

ในตัวอย่างนี้คุณมีลูปถาวรและเมื่อ server.accept ตอบสนองเธรดใหม่จะถูกสร้างขึ้นและเริ่มต้นทันทีเพื่อจัดการการเชื่อมต่อที่เพิ่งได้รับการยอมรับโดยใช้อ็อบเจ็กต์การเชื่อมต่อที่ส่งผ่านไปยังเธรด อย่างไรก็ตามโปรแกรมหลักจะวนกลับทันทีและรอการเชื่อมต่อใหม่

การใช้เธรด Ruby ในลักษณะนี้หมายความว่าโค้ดเป็นแบบพกพาและจะทำงานในลักษณะเดียวกันบน Linux, OS X และ Windows

เว็บเบราว์เซอร์ตัวจิ๋ว

เราสามารถใช้ไลบรารีซ็อกเก็ตเพื่อใช้อินเทอร์เน็ตโปรโตคอลใดก็ได้ ตัวอย่างเช่นในที่นี้คือรหัสสำหรับดึงเนื้อหาของหน้าเว็บ -

require 'socket'
 
host = 'www.tutorialspoint.com'     # The web server
port = 80                           # Default HTTP port
path = "/index.htm"                 # The file we want 

# This is the HTTP request we send to fetch a file
request = "GET #{path} HTTP/1.0\r\n\r\n"

socket = TCPSocket.open(host,port)  # Connect to server
socket.print(request)               # Send request
response = socket.read              # Read complete response
# Split response at first blank line into headers and body
headers,body = response.split("\r\n\r\n", 2) 
print body                          # And display it

ในการใช้งานเว็บไคลเอ็นต์ที่คล้ายกันคุณสามารถใช้ไลบรารีที่สร้างไว้ล่วงหน้าเช่น Net::HTTPสำหรับการทำงานกับ HTTP นี่คือรหัสที่เทียบเท่ากับรหัสก่อนหน้า -

require 'net/http'                  # The library we need
host = 'www.tutorialspoint.com'     # The web server
path = '/index.htm'                 # The file we want 

http = Net::HTTP.new(host)          # Create a connection
headers, body = http.get(path)      # Request the file
if headers.code == "200"            # Check the status code   
   print body                        
else                                
   puts "#{headers.code} #{headers.message}" 
end

โปรดตรวจสอบไลบรารีที่คล้ายกันเพื่อทำงานกับโปรโตคอล FTP, SMTP, POP และ IMAP

อ่านเพิ่มเติม

เราได้ให้คุณเริ่มต้นอย่างรวดเร็วในการเขียนโปรแกรมซ็อกเก็ต เป็นเรื่องใหญ่ดังนั้นขอแนะนำให้คุณอ่านRuby Socket Library และ Class Methodsเพื่อดูรายละเอียดเพิ่มเติม