基本的 Ruby TCP 服务器演示在启动时失败:`bind':地址已经在使用,Errno::EADDRINUSE [英] basic Ruby TCP server demo fails on startup: `bind': Address already in use, Errno::EADDRINUSE

查看:15
本文介绍了基本的 Ruby TCP 服务器演示在启动时失败:`bind':地址已经在使用,Errno::EADDRINUSE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 Ruby 展示一个简单的 TCP 服务器演示.我的第一个演示是使用经典的 C 风格 bind-listen-accept-read-write-close 方法.此代码第一次运行良好:

I am presenting a simple TCP server demo in Ruby. My first demo is using classical C-style bind-listen-accept-read-write-close methods. This code works well for the first time:

require 'socket'

class Server

  def start(bind: '127.0.0.1', port: nil, backlog: 1)

    Socket.new(:INET, :STREAM).tap do |sock|
      sock.bind Addrinfo.tcp bind, port
      sock.listen backlog

      # the codes of client connecting with it here is for reproducing the issue more easily
      c = Socket.new(:INET, :STREAM)
      c.connect Addrinfo.tcp '127.0.0.1', port

      client, client_addr = sock.accept
      puts "connected from #{client_addr.ip_address}:#{client_addr.ip_port}"

      client.puts "hi"

      client.close
      sock.close

    end
  end

end

Server.new.start(port: 23333)

然而,当我再次尝试运行它时,出现了 EADDRINUSE 的错误:

However when I tried to run it again, I got an errors of EADDRINUSE:

`some-script.rb:8:in `bind': Address already in use - bind(2) for 127.0.0.1:23333 (Errno::EADDRINUSE)`

大约 30 秒后,我可以再次成功启动脚本.不确定这是否由内核完成.

After about 30 seconds, I can start the script successfully again. Not sure if this is done by the kernel.

Socket#close 不是完全关闭套接字,内核关闭 TCP 连接吗?

Dosn't Socket#close fully close the socket and kernel close the TCP connection?

我在 Mac OS 10.11.1 和 Ubuntu 14.04 上都试过了,得到了相同的结果.在阅读了 ruby​​ 的源代码(socket.c)后,我仍然无法弄清楚.

I tried it on both Mac OS 10.11.1 and Ubuntu 14.04 and got the same result. After reading ruby's source code (socket.c) I still can't figure it out.

有什么建议吗?

推荐答案

您可以通过在调用之前调用 sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true) 来解决此问题sock.bind().

You can work around this by calling sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true) before the call to sock.bind().

这篇关于基本的 Ruby TCP 服务器演示在启动时失败:`bind':地址已经在使用,Errno::EADDRINUSE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆