【问题标题】:Python socket closed before all data have been consumed by remotePython套接字在远程使用所有数据之前关闭
【发布时间】:2015-08-17 16:44:41
【问题描述】:

我正在编写一个 Python 模块,它通过 unix 套接字与 go 程序进行通信。客户端(python 模块)向套接字写入数据,服务器使用它们。

# Simplified version of the code used
outputStream = socket.socket(socketfamily, sockettype, protocol)
outputStream.connect(socketaddress)
outputStream.setblocking(True)
outputStream.sendall(message)
....
outputStream.close()

我的问题是 Python 客户端倾向于在服务器有效读取数据之前完成并关闭套接字,这会导致服务器端出现“管道损坏,对等连接重置”。无论我做什么,对于 Python 代码,一切都已发送,因此对 send() sendall() select() 的调用都成功了......

提前致谢

编辑:由于 mac OS,我无法使用关机

EDIT2:我也尝试删除超时并调用 setblocking(True) 但它没有改变任何东西

EDIT3:在准备好这个问题http://bugs.python.org/issue6774之后,似乎文档是不必要的可怕所以我恢复了关机,但我仍然有同样的问题:

# Simplified version of the code used
outputStream = socket.socket(socketfamily, sockettype, protocol)
outputStream.connect(socketaddress)
outputStream.settimeout(5)
outputStream.sendall(message)
....
outputStream.shutdown(socket.SHUT_WR)
outputStream.close()

【问题讨论】:

    标签: python sockets


    【解决方案1】:

    在与一位了解 C 套接字的同事讨论后(在 cpython 中,套接字模块是 C 套接字的包装器),他谈到了这个http://ia600609.us.archive.org/22/items/TheUltimateSo_lingerPageOrWhyIsMyTcpNotReliable/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable.html(记录在案的 PHP 内部就是这样做的)

    TL&DR:关闭 + 快速轮询 + 关闭或 ioctl(SIOCOUTQ) 在 linux 上

    【讨论】:

      【解决方案2】:

      IHMO 最好使用异步 I/O 库/框架来完成。这是一个使用circuits的解决方案:

      服务器将接收到的内容回显到标准输出,客户端打开一个文件并将其发送到服务器,等待它完成,然后关闭套接字并终止。这是通过混合使用异步 I/O 和协程来完成的。

      server.py:

      from circuits import Component
      from circuits.net.sockets import UNIXServer
      
      class Server(Component):
      
          def init(self, path):
              UNIXServer(path).register(self)
      
          def read(self, sock, data):
              print(data)
      
      Server("/tmp/server.sock").run()
      

      client.py:

      import sys
      
      from circuits import Component, Event
      from circuits.net.sockets import UNIXClient
      from circuits.net.events import connect, close, write
      
      class done(Event):
          """done Event"""
      
      class sendfile(Event):
          """sendfile Event"""
      
      class Client(Component):
      
          def init(self, path, filename, bufsize=8192):
              self.path = path
              self.filename = filename
              self.bufsize = bufsize
      
              UNIXClient().register(self)
      
          def ready(self, *args):
              self.fire(connect(self.path))
      
          def connected(self, *args):
              self.fire(sendfile(self.filename, bufsize=self.bufsize))
      
          def done(self):
              raise SystemExit(0)
      
          def sendfile(self, filename, bufsize=8192):
              with open(filename, "r") as f:
                  while True:
                      try:
                          yield self.call(write(f.read(bufsize)))
                      except EOFError:
                          break
                      finally:
                          self.fire(close())
                          self.fire(done())
      
      Client(*sys.argv[1:]).run()
      

      在我对此的测试中,它的行为完全符合我的预期,没有 错误并且服务器在客户端关闭之前获取完整的文件 套接字并关闭。

      【讨论】:

        猜你喜欢
        • 2022-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多