Garfield
Garfield

Reputation: 1247

Ruby Sockets: Error (EINVAL) while trying to bind a sending socket to a port

The connect method fails giving an EINVAL when I am trying to connect from blue.example.edu to green.example.edu

I do not get this error when I connect from blue to blue itself.

The Ruby documentation under connect suggests

Errno::EINVAL - the address length used for the sockaddr is not a valid length for the address family or there is an invalid family in sockaddr

But since the same parameter is working correctly when I try connecting blue to another port on itself, this might be wrong ?

Here is the code snippet:

MY_NAME = Socket.gethostname
SERVER_NAME = "blue"    # Socket.gethostname returns 'blue' on the server
SERVER_IP = Socket::getaddrinfo(SERVER_NAME, 'www', nil, Socket::SOCK_STREAM)[0][3]  
#--> Gives me A.B.C.27 (see note on ipconfig below)

SERVER_LISTENING_PORT = 34900

MY_NAME = Socket.gethostname
MY_PORT_FOR_REQUESTING_SERVER = 40000

# other stuff

#CREATE
client_socket = Socket::new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
client_socket_addr = Socket.pack_sockaddr_in(MY_PORT_FOR_REQUESTING_SERVER, MY_NAME)

#BIND
client_socket.bind(client_socket_addr)

#CONNECT
server_addr = Socket.pack_sockaddr_in(SERVER_LISTENING_PORT, SERVER_NAME)
i_tried_with_ip_address_also = Socket.pack_sockaddr_in(SERVER_LISTENING_PORT, SERVER_IP)

#The line below raises the error
client_socket.connect(server_addr)

# more code below

Please note that hitting ifconfig on blue yields the same A.B.C.27 what the SERVER_IP contains

Under eth1 - inet addr:A.B.C.27, Bcast:A.B.C.255 Mask:255.255.255.0

I'm guessing this is related to the issue ?

Using Ruby 1.8.7 on Ubuntu machines

Please advice.


EDIT:

I used TCPSocket as suggested by zed_0xff in order to get this working temporarily. However I wish to know why the regular socket way is not working.

The only difference I can see is that using the Socket class, I am binding the client_socket_addr to a port from which I wish to send my data. TCPSocket sends data from a random port to the specified listening port on the server. What do I do if I wish to bind the sending to a specific port ?


EDIT2: Changed question title from:

Ruby Sockets: Errno::EINVAL: Invalid argument - connect(2)

So the answer from @zed_0xff has helped me tackle one of my problems of actually establishing a connection between the client and the server (Thank you!)

However, with that method, TCPSocket chooses a random sending port for sending data. Trying to binding the sending port to a particular port number fails.


PS: Please let me know if modifying the question name is against the community guidelines. Since my issue was only partially resolved, I edited the title it here itself and explained the edits in the "Edit" sections.

Upvotes: 1

Views: 3277

Answers (3)

ggsp
ggsp

Reputation: 452

I had the following in my specs:

url = "http://image.generator.example.com/100x100"
URI.parse(url).open

I was getting this error because the image placeholder generator had ceased working. Replacing the URL fixed things.

Upvotes: 0

alk
alk

Reputation: 70951

Getting EINVAL for bind() indicates that the address to bind to might still be in use.

To get around this

  • either use a different address (ip-address and/or port)
  • or if you are wanting to reuse a address, set the socket option SO_REUSEADDR on the socket prior to using it
  • or do not bind ... ;-)

Upvotes: 2

zed_0xff
zed_0xff

Reputation: 33227

maybe you should try with TCPSocket instead?

require 'socket'

s = TCPSocket.new SERVER_NAME, SERVER_LISTENING_PORT

while line = s.gets # Read lines from socket
  puts line         # and print them
end

s.close             # close socket when done

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/socket/rdoc/TCPSocket.html

Upvotes: 2

Related Questions