How to get other computer to connect to my localhost server? - ruby

I recently started learning Ruby Sockets and decided to research the topic. I came across the ruby-doc which had some example code that ran smoothly:
This is the example code for the server:
require 'socket'
server = TCPServer.new 2000 # Server bound to port 2000
loop do
client = server.accept # Wait for a client to connect
client.puts "Hello !"
client.puts "Time is #{Time.now}"
client.close
end
And the example code for the client:
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
So this ran well but I was wondering how I would get the client to connect if it is running from a different computer. So I attempted to replace the "'localhost'" in the client code with my public IP address courtesy of whatismyip.com, however, when I tried running the new client code on a different computer I merely got a timeout error. I even attempted running the new client code on the same machine running the server but still I got a timeout error.
Does anyone know how I can get this to work properly?
Any help would be much appreciated!

Greg Hewgill helped me figure this out:
My first problem was that I was using the wrong address. Greg suggested I check my actual address through the cmd command "ipconfig". The command gave me the actual address that the server was being hosted on. Through this I changed the "'localhost'" in the client code and changed it to the actual IP address. Upon running, I received an error that stated that the server had actively refused the connection. This was fixed by also changing the 'localhost' in the server code to the IP address of the server's machine.
Thank you Greg for the help!

Related

Keeping TCPSocket open: server or client's responsibility?

I have been reading examples online about Ruby's TCPSocket and TCPServer, but I still don't know and can't find what's the best practice for this. If you have a running TCPServer, and you want to keep the socket open across multiple connections/clients, who should be responsible in keeping them open, the server or the clients?
Let's say that you have a TCPServer running:
server = TCPServer.new(8000)
loop do
client = server.accept
while line = client.gets
# process data from client
end
client.puts "Response from server"
client.close # should server close the socket?
end
And Client:
socket = TCPSocket.new 'localhost', 8000
while line = socket.gets
# process data from server
end
socket.close # should client close the socket here?
All of the examples I have seen have the socket.close at the end, which I would assume is not what I want as that would close the connection. Server and clients should maintain open connection as they will need to send data back and forth.
PS: I'm pretty a noob on networking, so just kindly let me know if my question sounds completely dumb.
The server is usually responsible for keeping the connections open because the client (being the one connecting to the server) can break the connection at anytime.
Servers are usually in charge of everything that the client doesn't care about. A video game doesn't really care about the connection to the server as long as it's there. It just wants its data so it can keep running.

ruby socket connection to outside

I trying to make a connection with following ruby code
server
require 'socket'
puts "server"
socket = TCPServer.open(1000)
client = socket.accept
puts "connected"
client
require 'socket'
puts "client"
server= TCPSocket.open("172.30.1.2",1000)
puts "connected"
but client side always says target machine refused it.
no "connected" printing on both side
when I change "172.30.1.2" to "localhost", it works.
I wonder why I can't connect to my self
"172.30.1.2" is my IPv4 address
when I type ipconfig on cmd,
it says "172.30.1.2" is my ip.
I configure DMZ and port-forwarding too.
and all firewall is off.
I tried on windows xp and windows 7.
can someone help me?
(I want to connect to my computer from outside. and that's why I tried "172.30.1.2")
thanks.
In order to create server use TCPServer.open("172.30.1.2",1000)

Simple socket program in Ruby

I want to write a simple server socket in Ruby, which, when a client connects to it, prints a message and closes the client connection. I came up with:
require 'socket'
server = TCPServer.open('localhost',8800)
loop {
client = server.accept
Thread.start do
s = client
s.puts "Closing the connection. Bye!"
s.close
end
}
However, when I access "localhost:8800" in my browser, I am not getting that message, instead, it says page not found.. What am I doing wrong here?
It is quite likely that your browser is expecting something on the remote end that talks Http.
This is dependant upon your browser and also the exact URI you typed in. It is also possible that your browser is connecting getting the connection close and then displaying an error page.
If you want to see the server working then use telnet from a command prompt. So in one window type ruby ./myfilename.rb and then in another type telnet localhost 8800

Making a Ruby server work on port 80

I'm creating a simple web server in Ruby, which display's the text LOLZ in the browser. I have this now:
#!/usr/bin/ruby
require 'socket'
server = TCPServer.open(2000)
loop do
client = server.accept
client.puts "HTTP/1.1 200 OK\r\n"
client.puts "Content-type: text/plain\r\n"
client.puts "\r\n"
client.puts "LOLZ"
client.close
end
This works as expected. However, I want it to work on port 80. Whenever I change 2000 to 80, and start the server using bash, I get this error:
unknown-00-25-4b-8c-b9-b3:rServe koningbaardxiv$ ./rServe.rb
./rServe.rb:4:in `initialize': Permission denied - bind(2) (Errno::EACCES)
from ./rServe.rb:4:in `open'
from ./rServe.rb:4
Can anyone help me?
Thanks
EDIT: I just figured out that this is for all ports within a range of 0 to 999 :S
The ports below 1024 are reserved (also called well-known ports). You can access them only as root.
$ sudo ./rServe.rb
From http://www.iana.org/assignments/port-numbers:
The port numbers are divided into three ranges: the Well Known Ports,
the Registered Ports, and the Dynamic and/or Private Ports.
The Well Known Ports are those from 0 through 1023.
From http://www.linuxquestions.org/linux/articles/Technical/Why_can_only_root_listen_to_ports_below_1024:
I do not blame those who invented the port 1024 limit, it was a natural and important security feature given how UNIX machines were used in the 1970's and 1980's. A typical UNIX machine allowed a bunch of not necessarily fully trusted people to log in and do stuff. You don't want these untrusted users to be able to install a custom daemon pretending to be a well-known service such as telnet or ftp since that could be used to steal passwords and other nasty things.

Why am I not receiving UDP Packets sent to my own IP?

I've written this ruby program to send a UDP Packet to port 16800:
require 'socket'
sock = UDPSocket.new
sock.bind("", 47123)
sock.send("Hello!", 0, "192.168.0.100", 16800)
sock.close
where 192.168.0.100 is my own ip address. However, the packet doesn't show in Wireshark and my UDP server listening on port 16800 on the same PC (running Linux) isn't receiving anything.
When I slightly rewrite the program to
require 'socket'
sock = UDPSocket.new
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
sock.bind("", 47123)
sock.send("Hello!", 0, "<broadcast>", 16800)
sock.close
the packet does show up in Wireshark, but my server still isn't receiving anything.
Am I missing something obvious?
EDIT:
The server code, for completeness
require 'socket'
sock = UDPSocket.new
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
sock.bind(nil, 16800)
while true
packet = sock.recvfrom(1024)
puts packet
end
However, this was copied somewhere from the internet, and while editing it for stackoverflow, i found out that the server always receives packets sent to 127.0.0.1 but when I change nil to "", the server suddenly also receives the packets sent above. Is this a bug in the ruby socket implementation?
I just used your very code and the problem is you're not binding to a specific IP address. I don't know about Linux but on OS X there's an issue where sometimes the default will attach to an unused IP6 address rather than the interface you were expecting.
Changing "" to 192.168.1.255 on the server, and including "192.168.1.255" on the bind in the client made all this work for me :)
UDPSocket.BIND takes a host and a port. Try changing the nil to your IP address. From http://coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/; use
require 'socket'
def local_ip
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
UDPSocket.open do |s|
s.connect '64.233.187.99', 1
s.addr.last
end
ensure
Socket.do_not_reverse_lookup = orig
end
to get your IP
Have you tried sending to "localhost" or "127.0.0.1"? This will send directly to the local computer and will help diagnose the problem further.
Kind of speculating here, but you might want to consider something like this - when you use the computer's own IP, the packets aren't visible on the physical link b/c the tcp/ip stack doesn't have to push them that far to get them where they are going, it can turn them around internally to the computer at one of the higher layers in that seven-layer stack model (the 'transport' layer, perhaps?)
If such a connection is supposed to work, and you see the packages using Wireshark, then you should also check the software firewall on your machine. If it blocks traffic to the UDP port you want to use you can still see the package using Wireshark!

Resources