此代码来自 Coursera 上著名的 Python for Everyday 课程。
import socket
mysock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(("data.pr4e.org",80))
cmd = 'GET http://data.pr4e.org/romeo.txt HTTP/1.0\r\n\r\n'.encode()
mysock.send(cmd)
while True:
data = mysock.recv(512)
if len(data) < 1:
break
print(data.decode(), end='') # Decode the received bytes and print the data
mysock.close()
这效果很好并返回网址的内容。但是,当我想修改代码以便它请求网址并向程序提供输入时,它永远不会停止运行:
import socket
import re
mysock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
webad=input("Enter your web address:")
host_name=(re.findall("^(?:https?:\/\/)?(?:www\.)?([^\/\s]+)", webad))[0]
mysock.connect((host_name,80))
except Exception as e:
print(f"There is an error: {e}")
cmd_name=f"GET {webad}"+ " "+ r"HTTP/1.0\r\n\r\n"
cmd = cmd_name.encode()
mysock.send(cmd)
while True:
data = mysock.recv(512)
if len(data) < 1:
break
print(data.decode(), end='')
mysock.close()
我真的不明白问题是什么。我尝试检查解析的字符串等。它们都很好!然而,该程序会永远继续下去,而没有做它应该做的事情。
您的第一个问题是您发送的
cmd
。如果你打印原始的cmd,它将如下所示:
b'GET http://data.pr4e.org/romeo.txt HTTP/1.0\r\n\r\n'
当您修改后的代码发送此信息时
cmd
:
b'GET http://data.pr4e.org/romeo.txt HTTP/1.0\\r\\n\\r\\n'
发生这种情况是因为您正在使用
r"HTTP/1.0\r\n\r\n"
,它将 URL 这部分的 \
处理为文字字符串,这就是为什么您的代码卡在 data = mysock.recv(512)
行上,它甚至没有完成一次交互while 循环。它只是等待接收数据,但它无法接收数据,因为您连接的 url
不正确。
这是
socket
模块的正常行为,套接字以阻塞模式运行(这是默认设置)。你告诉它读取,它就会等待,直到新数据到达。如果你不希望它永远等待,你必须:
调用
socket.settimeout()
几秒钟,然后处理读取过程中发生的超时异常。
使用
select.select()
检测套接字何时有待读取的数据,然后调用 socket.recv() 读取 i