I'm trying to go through this particular code example from "The Well Grounded Rubyist" regarding TCPServer and threads. The code is below:
require 'socket'
server = TCPServer.new(3939)
connect = server.accept
connect.puts "Hi. Here's the date."
connect.puts 'date'
connect.close
server.close
How do I know what port is on my Macbook? The docs has 2000 in the example. However, when I try both of these numbers the code doesn't execute, it continues to hang indefinitely.
How can I check if these numbers are verified ports? I tried telnetting to the port number and the connection is refused everytime.
server.accepts waits for a client to connect to the server. If that does not happen, it just keeps waiting. Run the code, then open terminal and type:
require 'socket'
s = TCPSocket.new 'localhost', 3939
At this point you will create TCPSocket, which will connect with your server. This will cause the rest of the code to execute. You can check it with your socket:
while line = s.gets # Read lines from socket
puts line # and print them
end
Related
I have two network connected computers sending and receiving UDP data. Sending computer is Windows using SocketTest v 3.0.0
Receiving one is Macbook using this Ruby code for echo server:
require 'eventmachine'
EM.run do
puts "EM.run"
EM.open_datagram_socket '0.0.0.0', 9100 do |server|
puts "socket open"
def server.receive_data(data)
puts "data received: #{data}"
send_data("sending back: #{data}")
end
end
end
When I launch this program and send data from Windows computer, nothing happens. But, when I run this program for a second next to eventmachine echo:
require 'socket'
s = UDPSocket.new
while 1 do
puts "sending..."
s.send "hi", 0, "localhost", 9100
end
Eventmachine prints several "hi" messages as intended, and from now it also receives data from network-connected computer properly (I see "sending back" response on Windows computer).
Why is that? My understanding is that UDP is connectionless, so it should take everything from given port. How signal from "localhost" triggers socket to listen from network here?
OK, so I gave up investigating this and did a workaround:
require 'eventmachine'
require 'socket'
EM.run do
puts "EM.run"
EM.open_datagram_socket '0.0.0.0', 9100 do |server|
# send first packet from localhost to trigger network receiving (bug on my Macbook)
s = UDPSocket.new
s.send Time.now.to_s, 0, "localhost", 9100
def server.receive_data(data)
puts data
send_data("OK")
# forward data to another UDP port
s = UDPSocket.new
s.send data, 0, "localhost", 9101
end
end
end
Ugly, but works. s probably shouldn't be created two times but whatever. Now I can receive network packets in every program on port 9101.
I'm on Fedora 20 and use ruby 2.1.0. I've the following code from ruby-doc.
require 'socket'
s = TCPSocket.new 'localhost', 2000
while line = s.gets # Read lines from socket
puts line # and print them
end
s.close # close socket when done
Ruby throws the following error:
client.rb:3:in `initialize': Connection refused - connect(2) for "localhost" port 2000 (Errno::ECONNREFUSED)
from client.rb:3:in `new'
from client.rb:3:in `<main>'
What could be the reason for this failure? I mean, the code should definitively work, it's dead simple and from a recognized tutorial web page for ruby. I guess that the problem is my operating system, but how do I get it working properly?
Sockets are the endpoints of a bidirectional communications channel. Sockets may communicate within a process, between processes on the same machine, or between processes on different continents.
A Simple Client:
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
Now call TCPServer.open hostname, port function to specify a port for your service and create a TCPServer object.
A Simple Server:
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
}
read doc
I'm attempting to create a script in ruby that connects to a Minecraft server via TCP and fetches the current number of players much like the PHP script at http://www.webmaster-source.com/2012/07/05/checking-the-status-of-a-minecraft-server-with-php/
When running the code below I get �Took too long to log in
require 'socket'
server = TCPSocket.new '192.241.174.210', 25565
while line = server.gets
puts line
end
server.close
What am I doing wrong here?
you're not sending this:
fwrite($sock, "\xfe");
from the script you linked. You have to send that before you call read, like they do.
Basically the server is waiting for you to send data and when you don't after a timeout, you are disconnected.
I have a TCP server running which accepts the command "GETHELLO" and return "HELLO".
I test it by using Telnet in linux shell :
:~$ telnet 192.168.1.10 3000
Trying 192.168.1.10...
Connected to 192.168.1.10.
Escape character is '^]'.
GETHELLO
HELLO
How can I do this in ruby using TCPSocket ? (send "GETHELLO" and read the data "HELLO" returned by the server)
Thanks!
require 'socket'
sock = TCPSocket.new('192.168.1.10', 3000)
sock.write 'GETHELLO'
puts sock.read(5) # Since the response message has 5 bytes.
sock.close
I am looking for possibility to have ruby-based webserver communicating by pipe, not by TCP/IP. So I will send HTTP request by pipe and I want to read response by pipe. It should be used as bundled/internal webserver (RPC or something) for desktop application. I don't want to handle ports configuration when there will be more instances of my application running on same machine.
Any ideas?
Thank you in advance.
Try a UNIXSocket You use a local path to specify where the socket connection is,
not a port, and you can easily handle multiple simultaneous connections.
# server.rb
require 'socket'
File.delete( filename ) if File.exists? filename
server = UNIXServer.open( filename )
server.listen( queuesize )
puts "waiting on client connection"
while client= server.accept
puts "got client connection #{client.inspect}"
child_pid = fork do
puts "Asking the client what they want"
client.puts "Welcome to your server, what can I get for you?"
until client.eof?
line = client.gets
puts "The client wants #{line.chomp.inspect}"
end
client.close
end
puts "running server (#{child_pid})"
client.close
Process.detach(child_pid)
end
server.close
# client.rb
require 'socket'
puts "requesting server connection"
server = UNIXSocket.new( filename )
puts "got server connection #{server}"
line = server.gets
puts "The server said: #{line.chomp.inspect}"
%w{ a-pony a-puppy a-kitten a-million-dollars }.each do |item|
server.puts item
end
server.close
Pipe is for one-way communication, so there is no way you can set up webserver on that. You might try with unix socket. But really simplest solution is to use loopback (127.0.0.1). It's highly optimized, so the speed won't be a problem.
Not an answer to your question. However, if you do end up having to use a TCP/IP HTTP Server, you should ensure that it's only listening on 127.0.0.1. Listening on the local host address should be quite fast, as it won't hit the network, and will also make it a tad more secure to stop people connecting from the outside.
Thin supports unix sockets.