When/why 要使用 s.shutdown(socket.SHUT_WR)?
When/why to use s.shutdown(socket.SHUT_WR)?
我刚开始学习python网络编程。我正在阅读 Foundations of Python Network Programming 并且无法理解 s.shutdown(socket.SHUT_WR) 的用法,其中 s 是套接字对象。
这是使用它的代码(其中 sys.argv[2] 是用户要发送的字节数,四舍五入为 16 的倍数):
import socket, sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = '127.0.0.1'
PORT = 1060
if sys.argv[1:] == ['server']:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
while True:
print 'Listening at', s.getsockname()
sc, sockname = s.accept()
print 'Processing up to 1024 bytes at a time from', sockname
n = 0
while True:
message = sc.recv(1024)
if not message:
break
sc.sendall(message.upper()) # send it back uppercase
n += len(message)
print '\r%d bytes processed so far' % (n,),
sys.stdout.flush()
print
sc.close()
print 'Completed processing'
elif len(sys.argv) == 3 and sys.argv[1] == 'client' and sys.argv[2].isdigit():
bytes = (int(sys.argv[2]) + 15) // 16 * 16 # round up to // 16
message = 'capitalize this!' # 16-byte message to repeat over and over
print 'Sending', bytes, 'bytes of data, in chunks of 16 bytes'
s.connect((HOST, PORT))
sent = 0
while sent < bytes:
s.sendall(message)
sent += len(message)
print '\r%d bytes sent' % (sent,),
sys.stdout.flush()
print
s.shutdown(socket.SHUT_WR)
print 'Receiving all the data the server sends back'
received = 0
while True:
data = s.recv(42)
if not received:
print 'The first data received says', repr(data)
received += len(data)
if not data:
break
print '\r%d bytes received' % (received,),
s.close()
else:
print >>sys.stderr, 'usage: tcp_deadlock.py server | client <bytes>'
这是作者提供的解释,我觉得很难理解:
Second, you will see that the client makes a shutdown() call on the socket after it finishes sending its transmission. This solves an important problem: if the server is going to read forever until it sees end-of-file, then how will the client avoid having to do a full close() on the socket and thus forbid itself from doing the many recv() calls that it still needs to make to receive the server’s response? The solution is to “half-close” the socket—that is, to permanently shut down communication in one direction but without destroying the socket itself—so that the server can no longer read any data, but can still send any remaining reply back in the other direction, which will still be open.
我对它的理解是它会阻止客户端应用程序进一步发送数据,因此也会阻止服务器端进一步尝试读取任何数据。
我不明白的是,为什么要在这个程序中使用它,在什么情况下我应该考虑在我的程序中使用它?
这个解释是半生不熟的,它 仅 适用于这个特定的代码,总的来说,我会全票投票,认为这是不好的做法。
现在要了解为什么会这样,您需要查看服务器代码。该服务器通过阻塞执行来工作,直到它收到 1024 个字节。接收到数据后,它会处理数据(将其设为大写)并将其发回。现在问题出在硬编码值 1024 上。如果您的字符串短于 1024 字节怎么办?
要解决此问题,您需要告诉服务器 - 嘿,没有更多数据向您发送,因此 message = sc.recv(1024)
中的 return 并且您通过关闭一个方向的套接字来完成此操作.
您不想完全关闭套接字,因为那样服务器将无法向您发送回复。
My understanding of what it will do is that it will prevent the client
application from further sending the data and thus will also prevent
the server side from further attempting to read any data.
你的理解是正确的。
What I cant understand is that why is it used in this program …
正如您自己的陈述所暗示的那样,如果没有客户端的 s.shutdown(socket.SHUT_WR)
,服务器将不会停止等待数据,而是永远停留在其 sc.recv(1024)
中,因为不会有连接终止请求发送到服务器。
由于服务器永远不会到达它的sc.close()
,客户端也不会停止等待数据,而是永远停留在它的s.recv(42)
,因为不会有从发送的连接终止请求服务器。
阅读 this answer to "close vs shutdown socket?" 也可能会有所启发。
我刚开始学习python网络编程。我正在阅读 Foundations of Python Network Programming 并且无法理解 s.shutdown(socket.SHUT_WR) 的用法,其中 s 是套接字对象。 这是使用它的代码(其中 sys.argv[2] 是用户要发送的字节数,四舍五入为 16 的倍数):
import socket, sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = '127.0.0.1'
PORT = 1060
if sys.argv[1:] == ['server']:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
while True:
print 'Listening at', s.getsockname()
sc, sockname = s.accept()
print 'Processing up to 1024 bytes at a time from', sockname
n = 0
while True:
message = sc.recv(1024)
if not message:
break
sc.sendall(message.upper()) # send it back uppercase
n += len(message)
print '\r%d bytes processed so far' % (n,),
sys.stdout.flush()
print
sc.close()
print 'Completed processing'
elif len(sys.argv) == 3 and sys.argv[1] == 'client' and sys.argv[2].isdigit():
bytes = (int(sys.argv[2]) + 15) // 16 * 16 # round up to // 16
message = 'capitalize this!' # 16-byte message to repeat over and over
print 'Sending', bytes, 'bytes of data, in chunks of 16 bytes'
s.connect((HOST, PORT))
sent = 0
while sent < bytes:
s.sendall(message)
sent += len(message)
print '\r%d bytes sent' % (sent,),
sys.stdout.flush()
print
s.shutdown(socket.SHUT_WR)
print 'Receiving all the data the server sends back'
received = 0
while True:
data = s.recv(42)
if not received:
print 'The first data received says', repr(data)
received += len(data)
if not data:
break
print '\r%d bytes received' % (received,),
s.close()
else:
print >>sys.stderr, 'usage: tcp_deadlock.py server | client <bytes>'
这是作者提供的解释,我觉得很难理解:
Second, you will see that the client makes a shutdown() call on the socket after it finishes sending its transmission. This solves an important problem: if the server is going to read forever until it sees end-of-file, then how will the client avoid having to do a full close() on the socket and thus forbid itself from doing the many recv() calls that it still needs to make to receive the server’s response? The solution is to “half-close” the socket—that is, to permanently shut down communication in one direction but without destroying the socket itself—so that the server can no longer read any data, but can still send any remaining reply back in the other direction, which will still be open.
我对它的理解是它会阻止客户端应用程序进一步发送数据,因此也会阻止服务器端进一步尝试读取任何数据。
我不明白的是,为什么要在这个程序中使用它,在什么情况下我应该考虑在我的程序中使用它?
这个解释是半生不熟的,它 仅 适用于这个特定的代码,总的来说,我会全票投票,认为这是不好的做法。
现在要了解为什么会这样,您需要查看服务器代码。该服务器通过阻塞执行来工作,直到它收到 1024 个字节。接收到数据后,它会处理数据(将其设为大写)并将其发回。现在问题出在硬编码值 1024 上。如果您的字符串短于 1024 字节怎么办?
要解决此问题,您需要告诉服务器 - 嘿,没有更多数据向您发送,因此 message = sc.recv(1024)
中的 return 并且您通过关闭一个方向的套接字来完成此操作.
您不想完全关闭套接字,因为那样服务器将无法向您发送回复。
My understanding of what it will do is that it will prevent the client application from further sending the data and thus will also prevent the server side from further attempting to read any data.
你的理解是正确的。
What I cant understand is that why is it used in this program …
正如您自己的陈述所暗示的那样,如果没有客户端的 s.shutdown(socket.SHUT_WR)
,服务器将不会停止等待数据,而是永远停留在其 sc.recv(1024)
中,因为不会有连接终止请求发送到服务器。
由于服务器永远不会到达它的sc.close()
,客户端也不会停止等待数据,而是永远停留在它的s.recv(42)
,因为不会有从发送的连接终止请求服务器。
阅读 this answer to "close vs shutdown socket?" 也可能会有所启发。