OSError:[Erno 9]带有socket.shutdown()的错误文件描述符



我目前正在尝试了解套接字的工作方式。

我遵循了一个在线教程&蟒蛇HOWTO

我有一个服务器:

#!/usr/bin/env python3

import socket
HOST = '127.0.0.1' #standard loopback interface address (localhost)
PORT = 9999
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((HOST, PORT))
serversocket.listen()
(clientsocket, address) = serversocket.accept()
with clientsocket:
print('Connected by', address)
while True:
data = clientsocket.recv(1024)
if not data:
break
clientsocket.sendall(data)
clientsocket.shutdown(socket.SHUT_RDWR)
clientsocket.close()

和一个客户端:

#!/usr/bin/env python3
import socket
HOST = '127.0.0.1' #server hostname or IP address
PORT = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello world!')
data = s.recv(1024)
s.shutdown(socket.SHUT_RDWR)
s.close
print('Received', repr(data))

服务器监听连接,接受它,并回显它接收到的任何内容。

在python HOWTO中,强调始终关闭套接字。

现在,当我在不同的终端中运行这两个脚本时,客户端会按预期操作:

Received b'Hello world!'

带有服务器的终端给了我以下错误:

Connected by ('127.0.0.1, 42780')
Traceback (most recent call last):
File "echo-server.py", line 19, in <module>
clientsocket.shutdown(socket.SHUT_RDWR)
OSError: [Errno 9] Bad file descriptor

通过环顾四周,我了解到这是因为关闭了Python文件;外部";,即不是来自文件对象的close((,我认为这意味着我试图调用socket.shutdown()的套接字已经关闭。

现在,当我在服务器脚本中注释第19行时

#clientsocket.shutdown(socket.SHUT_RWDR)

一切都按预期进行,没有任何错误。

终端显示

Connected by ('127.0.0.1, 42780')

Received b'Hello world!'

据我所知,这种行为是由with语句引起的。

现在来谈谈我的实际问题:

  1. with语句是否通过完成该任务本身而使调用socket.shutdown()变得不必要
  2. 如果是,调用socket.close()是否仍然是必要的,还是由with语句完成?(评论这句话并没有给我任何不同的结果(

最后,我想确保如何从一开始就正确关闭套接字,因为HOWTO非常强调正确的形式。

closewith中是不必要的,因为它在退出with块时会自动调用close,但在with退出之前,shutdown仍然可以在其内部调用:

with clientsocket:
print('Connected by', address)
while True:
data = clientsocket.recv(1024)
if not data:
clientsocket.shutdown(socket.SHUT_RDWR)
break
clientsocket.sendall(data)

正如@Peter Wood所指出的,文档中确实包含了我问题的答案:

在3.2版中更改:添加了对上下文管理器协议的支持。退出上下文管理器相当于调用close((。

此外:

垃圾回收套接字时,套接字会自动关闭,但建议显式关闭((套接字,或在套接字周围使用with语句。

由于对已关闭的fileObject调用fileObject.close()不会产生错误,因此注释特定的行输出不会导致任何不同的结果。

我的解释是:

不打算在with语句中的套接字上显式调用socket.shutdown()

with语句中的套接字上调用socket.close()是不必要的。

相关内容

最新更新