【问题标题】:python socket connection refused on Mac but not on Windowspython套接字连接在Mac上被拒绝但在Windows上没有
【发布时间】:2017-08-15 05:22:25
【问题描述】:

这不是connection refused 的副本。这个问题询问MacOSWindows 之间的区别。另外我的Mac 上的防火墙是关闭的。

我正在尝试通过套接字与设备通信。代码写在python。出于某种原因,如果我在Windows 上运行我的代码,一切正常,但是如果我在Mac 上运行它,它就不行。我的一位同事在C 中编写了相同的代码并在Mac 上运行它并且没有任何问题。有人知道可能是什么问题吗?

如果需要,我可以提供更多详细信息。请让我知道哪些。

编辑

这里是代码

class Device(object):
    def __init__(self, ip_addr, port):
        self.ip_addr = ip_addr
        self.port = port

    def say_hi(self):
        msg = [254, 49, 0]
        ret = self.send_msg(msg)
        msg = [254, 29]
        return self.send_msg(msg)

    def say_bye(self):
        msg = [254, 49, 0]
        ret = self.send_msg(msg)
        msg = [254, 30]
        return self.send_msg(msg)

    def get_status(self):
        msg = [254, 49, 0]
        ret = self.send_msg(msg)
        msg = [254, 16]
        return self.send_msg(msg)

    def send_msg(self, msg):
        msg = ''.join(chr(i) for i in msg)
        s = socket.create_connection((self.ip_addr , self.port))
        s.sendall(msg)
        ret = s.recv(1)
        s.close()
        return ord(ret)

这是我得到的错误:

[Errno 61] Connection refused

错误发生在以下行:

s = socket.create_connection((self.ip_addr , self.port))

编辑 2

ip_addr='172.24.176.46', port='2101'

我可以访问该地址。以下是来自ping的结果

$ ping 172.24.176.46    
PING 172.24.176.46 (172.24.176.46): 56 data bytes
64 bytes from 172.24.176.46: icmp_seq=0 ttl=64 time=0.495 ms
64 bytes from 172.24.176.46: icmp_seq=1 ttl=64 time=0.398 ms
64 bytes from 172.24.176.46: icmp_seq=2 ttl=64 time=0.452 ms
^C

编辑 3

我找到了一个可以在 Windows 和 Mac 上运行的代码。我将在下面提供它,但本质上我所做的是在类初始化期间创建一个连接(即在__init__ 中)并且不要关闭send_msg 中的连接。这是我的问题:这样做是否安全和适当?不关闭连接似乎不是一个好方法。我将不胜感激。我的新代码如下。

class Device(object):
    def __init__(self, ip_addr, port):
        self.ip_addr = ip_addr
        self.port = port
        self.socket = socket.create_connection((self.ip_addr , self.port))

    def say_hi(self):
        msg = [254, 49, 0]
        ret = self.send_msg(msg)
        msg = [254, 29]
        return self.send_msg(msg)

    def say_bye(self):
        msg = [254, 49, 0]
        ret = self.send_msg(msg)
        msg = [254, 30]
        return self.send_msg(msg)

    def get_status(self):
        msg = [254, 49, 0]
        ret = self.send_msg(msg)
        msg = [254, 16]
        return self.send_msg(msg)

    def send_msg(self, msg):
        msg = ''.join(chr(i) for i in msg)
        self.socket.sendall(msg)
        ret = self.socket.recv(1)
        return ord(ret)

【问题讨论】:

  • 您发布的一些代码可能会有所帮助..
  • @abccd 添加了代码。
  • 查看这篇文章:connection refused 您很可能只需要禁用 Mac 的防火墙
  • self.ip_addr 的值是多少?您的 Mac 是否有权访问该地址?
  • @abccd 我的防火墙已关闭,我的问题与stackoverflow.com/questions/12394950/connection-refused 不同。在最近的编辑中提供了我的推理。

标签: python windows macos sockets


【解决方案1】:

根据我在 Mac 上的测试,你不能使用同一个套接字来监听。可能有一种方法可以以这种方式使用套接字,如果有的话,我建议您阅读 https://docs.python.org/2/howto/sockets.html#socket-howto

我只能让 python 使用两个不同的套接字进行连接,并分别创建客户端和服务器。对于服务器,代码如下所示:

      server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
      server.bind(('', self.port))
      server.listen(1)
      connection, client_addr = server.accept()
      connection.recv(1024)
      connection.close()
      server.close()

对于客户端,代码如下所示:

      client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
      try:
          client.connect(('10.6.6.11', 2101))
      except Exception:
          print 'Connection failed'
          sys.exit(1)
      client.sendall(msg)
      client.close()

如果您想修改任何其他内容,您必须填写空白。如果需要,您可以删除该 try catch。

【讨论】:

  • “不能使用同一个socket监听”是什么意思?你的意思是我不能打电话给client.recv(1)
  • 我试过你的代码。它没有用。我仍然收到“连接被拒绝”消息
  • 您需要使用两个不同的套接字。您似乎无法在端口 2101 上发送和接收。如果您在 2101 上接收,则必须使用不同的套接字将该数据发送到正在侦听的 2101 端口。根据 python 文档 recv() 应该与硬件和网络现实最佳匹配,bufsize 的值应该是 2 的相对较小的幂,例如 4096。
  • 如果你编辑 connection.read() 到 connection.recv(1024) 你应该能够让客户端和服务器互相交谈。我现在刚写完测试。
  • 问题是我无法编辑服务器。它正在设备上运行,我无法在设备上编辑代码。
【解决方案2】:

当我在其后放置一个小主循环时,您的原始代码对我来说运行良好(在 MAC 上)。

d = Device('127.0.0.1', 2101)
for n in range(5):
    d.say_hi()
    d.get_status()
    d.say_bye()

但是,您的新设计更接近完美。不,完全关闭连接不是一个好方法,但是关闭它,然后立即重新创建它也不是一个好的设计。

添加一个关闭函数并在完成对象后调用它怎么样?

def close(self):
    self.socket.close()

例如,我的代码将变为:

d = Device('127.0.0.1', 2101)
for n in range(5):
    d.say_hi()
    d.get_status()
    d.say_bye()
d.close()

(也可以添加一个 __del__ 析构函数,该析构函数将在对象不再被引用后自动调用,但这通常是个坏主意,因为在垃圾收集器运行之前不一定会调用它,这可能是下个月。与此同时,套接字描述符将保持打开状态。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-10
    • 2017-10-23
    • 2016-04-12
    • 2019-04-16
    • 1970-01-01
    • 2019-12-22
    • 1970-01-01
    • 2016-02-25
    相关资源
    最近更新 更多