如何实现Ruby后台TCPServer,不阻塞主脚本执行?
Got it, let's sort out this problem so your TCP server can run in the background while your main script keeps executing normally, and continuously accept and print responses on your target port.
The core issue with your original code is that server.accept is a blocking call—it pauses the entire script until a client connects. To fix this, we can use Ruby's threads to offload the server's listening logic to a background thread, freeing up the main thread to run your other code.
Modified Working Code
require 'socket' # Configure your server host and port srvhost = '0.0.0.0' # Listen on all network interfaces srvport = 12345 # Replace with your desired port # Spin up a background thread to handle the TCP server server_thread = Thread.new do server = TCPServer.open(srvhost, srvport) puts "TCP server started, listening on port #{srvport}..." # Loop indefinitely to accept multiple client connections loop do # This accept call blocks the background thread (not the main thread!) client = server.accept puts "New connection from: #{client.peeraddr[2]}:#{client.peeraddr[1]}" # Receive and print incoming data data = client.recv(1024) puts "Received data: #{data}" client.close puts "Connection closed\n" end end # Main thread continues executing your original logic puts "Main thread running other tasks..." # Your original CGI request code (unchanged) res = send_request_cgi({ 'uri' => "/", 'method' => 'GET', 'vars_get' => {'cmd' => rand_text_alphanumeric(10)} }) print "#{res.headers}" # Keep the main thread alive so the background server thread doesn't terminate server_thread.join
Key Details to Note
- Thread.new: This launches the server's listening loop in a separate background thread. The blocking
acceptcall now only pauses this background thread, not your main script. - loop do: Wrapping the accept logic in a loop ensures the server keeps accepting new connections indefinitely, instead of just one.
- server_thread.join: This tells the main thread to wait for the background server thread to finish (which it never will, thanks to the
loop). If your main script already has a continuous running loop (like processing other tasks), you can omit this line—just make sure the main thread doesn't exit early.
Bonus: Handling Concurrent Clients
If you need to handle multiple clients connecting at the same time, you can spin up a new thread for each client connection. This prevents one slow client from blocking others:
# Inside the server thread's loop loop do client = server.accept # Create a new thread for each client Thread.new(client) do |conn| puts "New connection from: #{conn.peeraddr[2]}:#{conn.peeraddr[1]}" data = conn.recv(1024) puts "Received data: #{data}" conn.close puts "Connection closed\n" end end
内容的提问来源于stack exchange,提问作者user8819420

