Python 2.7中的Web服务器:浏览器未显示页面
我正在用Python建立一个网络服务器,使用的是select()函数,也就是输入输出复用。这样我可以同时连接多个客户端,这些客户端就是网页浏览器(比如Safari、Chrome和Firefox),并且可以接收每个客户端的HTTP 1.1 GET请求。一旦我收到请求,就会把HTML页面的内容返回给浏览器,浏览器就会显示这个HTML页面。
我遇到的问题是,当我尝试保持连接一段时间时,发现浏览器里什么都显示不出来,直到我用fd.close()关闭连接。
这是我用来接受和响应浏览器请求的函数。问题在于,我在使用fd.sendall()之后,不想关闭连接,但页面在我关闭之前是不会显示的。希望能得到帮助!任何建议都非常感谢。
def handleConnectedSocket():
try:
recvIsComplete = False
rcvdStr = ''
line1 = "HTTP/1.1 200 OK\r\n"
line2 = "Server: Apache/1.3.12 (Unix)\r\n"
line3 = "Content-Type: text/html\r\n" # Alternately, "Content-Type: image/jpg\r\n"
line4 = "\r\n"
line1PageNotFound = "HTTP/1.1 404 Not Found\r\n"
ConnectionClose = "Connection: close\r\n"
while not recvIsComplete:
rcvdStr = fd.recv( 1024 )
if rcvdStr!= "" :
# look for the string that contains the html page
recvIsComplete = True
RequestedFile = ""
start = rcvdStr.find('/') + 1
end = rcvdStr.find(' ', start)
RequestedFile = rcvdStr[start:end] #requested page in the form of xyz.html
try:
FiletoRead = file(RequestedFile , 'r')
except:
FiletoRead = file('PageNotFound.html' , 'r')
response = FiletoRead.read()
request_dict[fd].append(line1PageNotFound + line2 + ConnectionClose + line4)
fd.sendall( line1PageNotFound + line2 + line3 + ConnectionClose + line4 + response )
# fd.close() <--- DONT WANT TO USE THIS
else:
response = FiletoRead.read()
request_dict[fd].append(line1 + line2 + line3 + ConnectionClose + line4 + response)
fd.sendall(line1 + line2 + line3 + line4 + response)
# fd.close() <--- DONT WANT TO USE THIS
else:
recvIsComplete = True
#Remove messages from dictionary
del request_dict[fd]
fd.close()
客户端(浏览器)的请求是HTTP 1.1格式,如下所示:
GET /Test.html HTTP/1.1
Host: 127.0.0.1:22222
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: keep-alive
1 个回答
1
Connection: close
是告诉浏览器你会通过关闭连接来结束数据传输的意思。但你可能不想这样,所以你可以用其他的值,比如Keep-Alive
。不过如果你用这个,记得还要发送 Content-Length
,或者做其他事情,这样浏览器才能知道你什么时候结束数据传输。
即使你不使用 Keep-Alive
,发送 Content-Length
也是个好主意,因为它可以让浏览器知道下载页面的进度。如果你发送了一个大文件,但没有发送 Content-Length
,浏览器就不能显示进度条。Content-Length
就是用来实现这个功能的。
那么,怎么发送 Content-Length
这个头信息呢?你需要计算一下你要发送的数据的字节数。把这个数字转成字符串,然后用这个作为值。就是这么简单。例如:
# Assuming data is a byte string.
# (If you're dealing with a Unicode string, encode it first.)
content_length_header = "Content-Length: {0}\r\n".format(len(data))
这里有一些我正在使用的代码:
#!/usr/bin/env python3
import time
import socket
data = b'''\
HTTP/1.1 200 OK\r\n\
Connection: keep-alive\r\n\
Content-Type: text/html\r\n\
Content-Length: 6\r\n\
\r\n\
Hello!\
'''
def main(server_address=('0.0.0.0', 8000)):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
server.bind(server_address)
server.listen(5)
while True:
try:
client, client_address = server.accept()
handle_request(client, client_address)
except KeyboardInterrupt:
break
def handle_request(client, address):
with client:
client.sendall(data)
time.sleep(5) # Keep the socket open for a bit longer.
client.shutdown(socket.SHUT_RDWR)
if __name__ == '__main__':
main()