【问题标题】:Ruby Sockets: Error (EINVAL) while trying to bind a sending socket to a portRuby 套接字:尝试将发送套接字绑定到端口时出错 (EINVAL)
【发布时间】:2012-11-29 18:11:33
【问题描述】:

当我尝试从blue.example.edu 连接到green.example.edu 时,connect 方法无法给出EINVAL

当我从 blue 连接到 blue 本身时,我没有收到此错误。

connect 下的 Ruby documentation 建议

Errno::EINVAL - 用于 sockaddr 的地址长度不是 地址族的有效长度或存在无效族 sockaddr

但是由于当我尝试将蓝色连接到自身的另一个端口时,相同的参数工作正常,这可能是错误的?

这里是sn-p的代码:

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

请注意,在蓝色上点击 ifconfig 会产生相同的 A.B.C.27 SERVER_IP 包含的内容

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

我猜这与问题有关?

Ubuntu 机器上使用 Ruby 1.8.7

请指教。


编辑:

我按照 zed_0xff 的建议使用了 TCPSocket,以便暂时使其正常工作。 但是我想知道为什么常规套接字方式不起作用。

我能看到的唯一区别是,使用 Socket 类,我将client_socket_addr 绑定到我希望从中发送数据的端口。 TCPSocket 将数据从随机端口发送到服务器上指定的侦听端口。 如果我希望将发送绑定到特定端口该怎么办?


EDIT2:将问题标题更改为:

Ruby 套接字:Errno::EINVAL:无效参数 - connect(2)

所以@zed_0xff 的回答帮助我解决了在客户端和服务器之间实际建立连接的问题之一(谢谢!)

但是,使用该方法,TCPSocket 会选择一个随机发送端口来发送数据。尝试将发送端口绑定到特定端口号失败。


PS:如果修改问题名称违反社区准则,请告诉我。由于我的问题只得到了部分解决,我在这里自己编辑了标题,并在“编辑”部分解释了编辑。

【问题讨论】:

  • 你会循环尝试这个吗?如果是这样:MY_PORT_FOR_REQUESTING_SERVER 可能仍在使用中。

标签: ruby sockets tcp ip


【解决方案1】:

bind() 获取EINVAL 表示要绑定的地址可能仍在使用中。

解决这个问题

  • 要么使用不同的地址(IP 地址和/或端口)
  • 或者如果您想重用地址,请在使用前在套接字上设置套接字选项SO_REUSEADDR
  • 或者不绑定... ;-)

【讨论】:

    【解决方案2】:

    也许您应该尝试改用 TCPSocket?

    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

    【讨论】:

    • 感谢您对 zed_0xff 的回复。使用 TCPSocket 有效。但是知道为什么较低级别的 Socket 类不起作用吗?
    【解决方案3】:

    我的规格中有以下内容:

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

    我收到此错误是因为图像占位符生成器已停止工作。替换 URL 固定的东西。

    【讨论】:

      猜你喜欢
      • 2016-01-15
      • 2021-08-25
      • 1970-01-01
      • 1970-01-01
      • 2016-10-23
      • 1970-01-01
      • 2013-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多