Ruby socket binding on system w/ multiple interfaces - ruby

I have a computer with 2 interfaces, eth0 (192.168.251.10) and eth1 (192.168.251.11), and I'm trying to have two instances of a Ruby application listen on each of them. They should both listen on the same port, just on different interfaces. The interface to be binded to specified via command line args during runtime.
Regardless of the order I start the application, the one listening on eth0 will always succeed, but the one listening on eth1 will always not receive anything. I checked using Wireshark and shows the packets are being received, but is the Ruby application isn't getting anything.
I've tried with a very simple textbook case code, so I'm very puzzled as to why it doesn't work
BasicSocket.do_not_reverse_lookup = true
socket = UDPSocket.new
ip_addr = ARGV[0]
port = 8722
socket.bind(ip_addr, port)
puts "Listener started on #{ip_addr}:#{port}"
while(true)
msg, sender_sockaddr = socket.recvfrom(1024)
end
I'm running Ruby 1.8.7 on Ubuntu 12.04 LTS. Something else I noticed is that if I bring down both the interfaces, and then up again, it will work on the first interface that was brought up, but not the second.
Output from netstat seems correct, showing listening on two different addresses.
Proto Recv-Q Send-Q Local Address Foreign Address State
udp 0 0 0.0.0.0:68 0.0.0.0:*
udp 0 0 192.168.251.10:8722 0.0.0.0:*
udp 0 0 192.168.251.11:8722 0.0.0.0:*
udp 0 0 0.0.0.0:5353 0.0.0.0:*
udp 0 0 0.0.0.0:54506 0.0.0.0:*
udp6 0 0 :::38033 :::*
udp6 0 0 :::5353 :::*

This is not a standard way to setup an app. Hard coding networking assignments is not recommended. You'd be better of using a load balancer and let it handle the interface assignments.

Related

golang http server http.ListenAndServe only works for localhost?

I tied to implement an HTTP server in Azure Linux VM using golang. Below is the simple golang server code, listening on port 30175. And there is no firewall on that port.
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":30175", nil))
}
The result of sudo netstat -tlnp is:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 1605/vsftpd
tcp 0 0 127.0.0.1:3350 0.0.0.0:* LISTEN 1873/xrdp-sesman
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1697/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1379/cupsd
tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN 4879/8
tcp 0 0 127.0.0.1:6011 0.0.0.0:* LISTEN 15507/9
tcp 0 0 0.0.0.0:3389 0.0.0.0:* LISTEN 1859/xrdp
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 2112/python
tcp6 0 0 :::22 :::* LISTEN 1697/sshd
tcp6 0 0 ::1:631 :::* LISTEN 1379/cupsd
tcp6 0 0 ::1:6010 :::* LISTEN 4879/8
tcp6 0 0 ::1:6011 :::* LISTEN 15507/9
tcp6 0 0 :::30175 :::* LISTEN 46595/HttpHandler
I can get response only in localhost, but no response from remote server:
curl localhost:30175
Hi there, I love !
curl serveripaddress:30175
not working
Your problem is that your server is listening on tcp6 stack. Try to explicitly use tcp with “0.0.0.0:6789” instead of just port “:6789”
This has nothing to do with your code. It is a typical firewall issue.
By default (on *nix platform) all the incoming traffic is blocked and all outgoing is allowed. You need to open the ports on your OS to allow incoming traffic to hit your servers. try installing ufw utility and run sudo ufw allow 30175
From the question, it seems your server is using tcp6. Ideally, it should not cause the problem because tcp6 is supposed to support both IPV4 as well as IPV6. But I would recommend you to downgrade it to tcp, if that makes sense.
You are trying to output to console. Did you try to send it as a response?
func handler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(fmt.Sprintf("Hi there, I love %s!", r.URL.Path[1:])));
}
No if you don't specify the host part of the address the server will listen on every available unicast address and every available anycast address of the system. So I would guess a problem in name resolution or routing.
This is due to Linux listen rules.
There is a reject all rule on my rules.
# listen rules
sudo iptables -L INPUT --line-numbers
sudo iptables -D INPUT 8

What's the underlying transport layer protocol when etcd node sends out a heartbeat

Should it be UDP or TCP? If it's the latter one, wouldn't it cost too much overhead on network via three-time shaking and four-time waving?
$ sudo netstat -nap | grep etcd
[sudo] password for emma:
tcp 0 0 127.0.0.1:7001 0.0.0.0:* LISTEN 21731/etcd
tcp 0 0 127.0.0.1:4001 0.0.0.0:* LISTEN 21731/etcd
tcp 0 0 127.0.0.1:2379 0.0.0.0:* LISTEN 21731/etcd
tcp 0 0 127.0.0.1:2380 0.0.0.0:* LISTEN 21731/etcd

netstat: parse (awk?) output to return "Program name" not "PID/Program name"

UBUNTU 14.04
netstat -p outputs both "PID/Program name" in the same column. I just want "Program name" in that column. What's the easiest way to do this?
Actual Output
root#neo4j1:~# netstat -tlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 *:ssh *:* LISTEN 1020/sshd
tcp6 0 0 [::]:ssh [::]:* LISTEN 1020/sshd
tcp6 0 0 [::]:7473 [::]:* LISTEN 31380/java
tcp6 0 0 [::]:7474 [::]:* LISTEN 31380/java
Desired Output
root#neo4j1:~# netstat -tlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State Program name
tcp 0 0 *:ssh *:* LISTEN sshd
tcp6 0 0 [::]:ssh [::]:* LISTEN sshd
tcp6 0 0 [::]:7473 [::]:* LISTEN java
tcp6 0 0 [::]:7474 [::]:* LISTEN java
Try
netstat -tlp | sed 's,[0-9]\+/,,'
Using grouping with Sed:
netstat -tlp | sed 's/\(^.*\)\( [0-9]*\/\)\(.*$\)/\1\3/g'
Though RTLinuxSW's answer is much cleaner.

Use eventmachine with sinatra, why it will always quit?

why it always quit when i run this ruby program ?
This is the ruby program:
require 'rubygems'
require 'eventmachine'
require 'thread'
require 'sinatra'
Thread.new do
EventMachine.run do
EM.add_periodic_timer(1) do
#do some things
end
end
end
get '/' do
'hello'
end
when i run it, i got this:
lynn#ubuntu:~/Test$ ruby em1.rb
== Sinatra/1.4.2 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.5.1 codename Straight Razor)
>> Maximum connections set to 1024
>> Listening on localhost:4567, CTRL+C to stop
lynn#ubuntu:~/Test$
lynn#ubuntu:~/Test$ netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
tcp 28 0 192.168.241.134:38223 91.189.92.11:443 CLOSE_WAIT
tcp 1 0 192.168.241.134:42978 91.189.94.25:80 CLOSE_WAIT
tcp6 0 0 :::22 :::* LISTEN
tcp6 0 0 ::1:631 :::* LISTEN
lynn#ubuntu:~/Test$
it was quit when i run this ruby program, why? here i wanna a thread to periodicaly do some things with the http request! how can i do it ?
Just run your Sinatra app under thin server and it will be fired with Eventmachine

Problem connecting a linux server and windows client with sockets

Hello all
I am trying to learn more about sockets and how to use them and I have been stuck on an issue for a while now.
I started with Beej's guide to network programming and I made the talker and listener from this page on the linux (Fedora 14) machine I am working on. It works and I can get it to talk to each other.
Then I went on to Windows (7) and worked with this tutorial and got that up and running and can send messages to myself on the windows machine. The only change I really have is that I am using getHostbyAddr and not by name.
It is when I glue the two together that I start to get issues, or rather one issue for now. I am running listener from Beej on the linux machine and I try to have the client from Johnnie send it a message. I get a winsock error 10061 on the windows machine and nothing ever shows up on the linux (not surprisingly). I have tested this with the firewall on the linux and I still get that error.
What can I do to fix this?
Thank you
Edited to add some more info:
When I run tcpdump I get this
[root#localhost ~]# tcpdump tcp port 4950
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
12:08:56.246753 IP TLARGE.WIFI.schoolname.EDU.62394 > hmd46.cs.schoolname.edu.sybasesrvmon: Flags [S], seq 150153995, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0
12:08:56.246794 IP hmd46.cs.schoolname.edu.sybasesrvmon > TLARGE.WIFI.schoolname.EDU.62394: Flags [R.], seq 0, ack 150153996, win 0, length 0
12:08:56.746170 IP TLARGE.WIFI.schoolname.EDU.62394 > hmd46.cs.schoolname.edu.sybasesrvmon: Flags [S], seq 150153995, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0
12:08:56.746221 IP hmd46.cs.schoolname.edu.sybasesrvmon > TLARGE.WIFI.schoolname.EDU.62394: Flags [R.], seq 0, ack 1, win 0, length 0
12:08:57.246138 IP TLARGE.WIFI.schoolname.EDU.62394 > hmd46.cs.schoolname.edu.sybasesrvmon: Flags [S], seq 150153995, win 8192, options [mss 1460,nop,nop,sackOK], length 0
12:08:57.246185 IP hmd46.cs.schoolname.edu.sybasesrvmon > TONJELARGE.WIFI.schoolname.EDU.62394: Flags [R.], seq 0, ack 1, win 0, length 0
^C
6 packets captured
6 packets received by filter
0 packets dropped by kernel
Running netstat gives me this:
[root#localhost ~]# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:58661 0.0.0.0:* LISTEN 1083/rpc.statd
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1013/rpcbind
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1265/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1148/cupsd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1554/sendmail: acce
tcp 0 0 :::56315 :::* LISTEN 1083/rpc.statd
tcp 0 0 :::111 :::* LISTEN 1013/rpcbind
tcp 0 0 :::22 :::* LISTEN 1265/sshd
tcp 0 0 ::1:631 :::* LISTEN 1148/cupsd
Both of these were from the linux machine
Error 10061 means WSAECONNREFUSED. In the link you posted I see the client is using port 80. Are you sure you modified it to 4950 ?
Something is definitely getting through to the server, otherwise it wouldn't send you the "I don't like you" RST (that's what connection refused means: not only does it refuse your connection, to add insult to injury it's telling you).
EDIT 1
From the netstat output it seems nobody is listening on 4950.
EDIT 2
I finally brought myself to read that beej stuff (to be honest I always considered his tutorials the worst). Didn't this set off any alarm ? You're creating a udp socket, that's why nobody is listening in TCP 4950, that's why you can't connect.
hints.ai_socktype = SOCK_DGRAM;
You have two options:
Use a UDP socket in the windows side
Change the code on the server side to use TCP.
The server code as it stands isn't suitable for TCP (recvfrom and all that stuff) but should be easily adapted).

Resources