HTTP中确定报文结束的方法

智码破浪客
• 阅读 3756

HTTP中,确定报文结束有几种不同方法,较为常见的是:

关闭TCP连接
通过Content-Length检测
若不关闭TCP连接,也不在HTTP头部加上Content-Length字段,则无法正确确定HTTP报文是否结束,对于浏览器来说,此时就会一直处于加载状态。

这几天学习Python Socket编程时就遇到了这个问题,下面是一段最简单的HTTP服务器代码,无论收到什么请求都返回一个Hello World!
`
from socket import socket, AF_INET, SOCK_STREAM

HTTPResponse ='HTTP/1.1 200 OKrnrn<html>Hello World!</html>'

WebSocket = socket(AF_INET, SOCK_STREAM)
WebSocket.bind(('localhost', 80))
WebSocket.listen(1)

HTTPSocket, addr = WebSocket.accept() # Wait Connection

while True:
print 'Waiting HTTP Request...'
Request = HTTPSocket.recv(1024)

print 'Send HTTP Response!'
HTTPSocket.sendall(HTTPResponse)
`
然而,这段代码是无法正常工作的,运行之后使用浏览器访问http://localhost/,得到的结果是这样的:
HTTP中确定报文结束的方法

从Shell的输出结果来看,HTTP响应报文已经发送成功了,此时服务器已经在等待下一次请求了,而浏览器却始终处于Connecting状态中。

可以通过由服务器主动关闭TCP连接来解决这一问题,修改后的代码是这样的:
`
from socket import socket, AF_INET, SOCK_STREAM

HTTPResponse ='HTTP/1.1 200 OKrnrn<html>Hello World!</html>'

WebSocket = socket(AF_INET, SOCK_STREAM)
WebSocket.bind(('localhost', 80))
WebSocket.listen(1)

while True:
print 'Waiting HTTP Request...'
HTTPSocket, addr = WebSocket.accept() # Wait Connection
Request = HTTPSocket.recv(1024)

print 'Send HTTP Response!'
HTTPSocket.sendall(HTTPResponse)

HTTPSocket.close() # Close Connection`
修改后就可以正常运行了:

如果不关闭TCP连接,也可以通过加上Content-Length字段来解决这一问题,代码如下:
`
from socket import socket, AF_INET, SOCK_STREAM

HTTPResponse ='HTTP/1.1 200 OKrnContent-Length: 25rnrn<html>Hello World!</html>'

WebSocket = socket(AF_INET, SOCK_STREAM)
WebSocket.bind(('localhost', 80))
WebSocket.listen(1)

HTTPSocket, addr = WebSocket.accept() # Wait Connection

while True:
print 'Waiting HTTP Request...'
Request = HTTPSocket.recv(1024)

print 'Send HTTP Response!'
HTTPSocket.sendall(HTTPResponse)`
这样浏览器也可以正常访问服务器,运行结果和之前关闭TCP连接完全相同。

一般来说,没有必要始终维持着一个TCP连接,所以最佳的解决方案是:使用Content-Length字段,并且在每次响应之后关闭TCP连接,即以下代码:
`
from socket import socket, AF_INET, SOCK_STREAM

HTTPResponse ='HTTP/1.1 200 OKrnContent-Length: 25rnrn<html>Hello World!</html>'

WebSocket = socket(AF_INET, SOCK_STREAM)
WebSocket.bind(('localhost', 80))
WebSocket.listen(1)

while True:
print 'Waiting HTTP Request...'
HTTPSocket, addr = WebSocket.accept() # Wait Connection
Request = HTTPSocket.recv(1024)

print 'Send HTTP Response!'
HTTPSocket.sendall(HTTPResponse)

HTTPSocket.close() # Close Connection`

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
TCP之RST报文段
TCP首部中的RST比特是用于"复位"的。一般来说,无论何时一个报文段发往基准的连接(referencedconnection)出现错误,TCP都会发出一个复位报文段("基准的连接"指由目的IP地址和目的端口号以及源IP地址和源端口号指明的连接)。1\.到不存在的端口的连接请求产生复位的一种
东方客主 东方客主
4年前
Http协议详解
超文本传输协议请求/响应报文连接建立的流程HTTP的特点请求/响应报文请求报文(https://imghelloworld.osscnbeijing.aliyuncs.com/146ca2b87d6a82b2c5c101154d9
Wesley13 Wesley13
3年前
HTTP报文
一、HTTP概述(一)什么是HTTP协议?  当在web页面输入url后,浏览器会向web服务器请求资源以显示web页面,而它们之间使用的就是HTTP协议(HyperTextTransferProtocol,超文本传输协议),浏览器就是基于HTTP协议进行文档传输的。(二)HTTP协议的特点1、
Wesley13 Wesley13
3年前
HTTP协议图
1.首部字段概述先来回顾一下首部字段在报文的位置,HTTP报文包含报文首部和报文主体,报文首部包含请求行(或状态行)和首部字段。在报文众多的字段当中,HTTP首部字段包含的信息最为丰富。首部字段同时存在于请求和响应报文内,并涵盖HTTP报文相关的内容信息。使用首部字段是为了给客服端和服务器端提供报文主体大小、所使用的语言、认证信息
Wesley13 Wesley13
3年前
DHCP协议报文
DICP协议采用客户端服务器方式进行交互,其报文格式共有8种,由报文中“DHCPmessage0pe”字段的值来确定,后面括号中的值即为相应类型的值,具体含义如下1、DHCPDiscover报文,是客户端开始DHCP过程的第一个报文。2\.DHCPOfer报文,是服务器对DHCP\_Discover报文的响应3\.D
Wesley13 Wesley13
3年前
HTTP报文内的HTTP信息之请求报文及响应报文的结构
HTTP报文用于HTTP协议交互的信息被称为HTTP报文。请求端(客户端)的HTTP报文叫做请求报文,响应端(服务器端)的叫做响应报文。HTTP报文本身是由多行(用CRLF作换行符,就是回车加换行)数据构成的字符串文本。HTTP报文大致可分为报文首部和报文主体两块。两者由最初出现的空行(CRLF)来划分。通常,
Stella981 Stella981
3年前
Django_初识
HTTP协议超文本传输协议(应用层的,基于tcp\ip协议的)特点:无状态,无连接(短连接)请求消息格式:请求行\请求头部\空行\请求数据请求行:GET路径HTTP/1.1响应消息格式:响应行\响应头部\空行\响应数据响应行:HTTP/1.1状态码状态
Wesley13 Wesley13
3年前
TCP和UDP的常见面试题
问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYNACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FI
Easter79 Easter79
3年前
TCP四次挥手客户端关闭链接为什么要等待2倍MSL
最长报文寿命  在TCP协议中,当发送方发送释放连接报文收到确认报文后,只是在一个方向上断开了TCP连接,然后,接收方发送释放连接的报文,发送方回复确认。此时,连接还没有释放,发送方要等待2MSL(maximumsegmentlifetime——最大的生命周期)后关闭连接。问题  主动发起关闭连接的操作的一方将达到TIME
Stella981 Stella981
3年前
HTTP协议:不可小觑的Content
接上一篇《用Netty实现的简单HTTP服务器(http://my.oschina.net/u/203921/blog/93076)》,本篇文章摘自《HTTP权威指南》。ContentLength首部告诉浏览器报文中实体主体的大小。这个大小是包含了内容编码的,比如对文件进行了gzip压缩,ContentLength就是压缩后的大小(这点对我们编写
Stella981 Stella981
3年前
Android用户操作web后台登录后获取cookie安全通行证认知
     HTTP客户端编程中最常碰见的问题,很多网站的内容都只是对注册用户可见的,这种情况下就必须要求使用正确的用户名和口令登录成功后,方可浏览到想要的页面。因为HTTP协议是无状态的,也就是连接的有效期只限于当前请求,请求内容结束后连接就关闭了。在这种情况下为了保存用户的登录信息必须使用到Cookie机制。以JSP/Servlet为例,当浏览器请
智码破浪客
智码破浪客
Lv1
坐到三更尽,归仍万里赊。
文章
5
粉丝
0
获赞
0