最近想在node.js上面模拟Transfer-Encoding:chucked时的发包。无奈不加上Connection:keep-alive本地怎么也接收不了完整的数据报。无奈只好尝试在writeHead上面加上这个协议头,不过问题是Vary,Transfer-Encoding,Cookie之类的协议头都发出去了,而这个协议头貌似被无视了。不知道跟express有无关系,还是node.js本身就不能设置这个协议头。因为我只有一个部分要使用到这样的流式传输,别的部分我要用express的res.send来发包,所以不能离开express。所以希望大家能帮我想一个不舍弃使用express也能实现这个功能的办法。
代码在下面:
exports.action = function (req, res) {
res.writeHead(200, {
'Content-Type': 'text/xml;charset=ISO-8859-1',
'Transfer-Encoding': 'chunked',
'Vary': 'Accept-Encoding',
'Set-Cookie': 'test=1;',
'Connection': 'keep-alive'}); //最后一行怎么加都没用 用express的set也不行
res.write(respondData(SoapSign,ParseData(SoapBody[0])));
res.end();
};
在此先感谢回复的大神们
@mypayne keep-alive,是http1.0的产物,http1.0中http的底层socket连接默认都是短连接,但是有时候为了节省tcp的连接建立开销,才有了keep-alive这么一说。即一次http连接结束后,尽量保持当前的tcp连接不中断,让客户端在下次再和服务器通信的时候能够复用这个tcp连接;但是服务器又不忍心让自己的tcp连接白白被客户端长期霸占,所以服务器端会在某个时候悄悄的把某个keep-alive的连接断开,以减轻自己的资源损耗。 但是在http1.1中是不存在keep-alive和非keep-alive的区别的,因为它默认就是长连接,只不过它在服务器端同样采取的是使用某种策略定期回收这些长连接。 当然我前面讲的这些理论不知道能否帮你解决问题,但是我要说的是node的http中默认就是使用http1.1,Connection:kepp-alive默认就是存在的,Transfer-Encoding:chucked也是其默认的数据传输方式。至于你的情形是怎么出现的,我表示怀疑。
@yunnysunny 问题是本地客户端对于数据包多于1个的数据报一定要看到Connection:keep-alive才继续接收。我自己也没法修改那个客户端,客户端的开发文档就写这样。按你的说法来推测这个客户端应该是不按标准的。原来的php没迁移的时候是有Connection:keep-alive的,因此迫于无奈只能在node.js服务端补上这个协议头。然而node.js不给我加上这个协议头,所以才希望找到一个加上这个协议头的办法,不然最关键的部分没法做下去了。
@yunnysunny 用上面的代码传回来就没有 用常规方法会返回含Content-Length的。
HTTP/1.1 200 OK
x-powered-by: Express
content-type: text/xml;charset=ISO-8859-1
vary: Accept-Encoding
set-cookie: debug=1;Path=/
date: Sun, 27 Oct 2013 07:52:56 GMT
Server: Null
Transfer-Encoding: chunked
490
@mypayne Transfer-Encoding: chunked,如果有这个头,是服务器在告诉客户端,我的数据不是一次性发完的,我需要多次发送,所以数据的总长度Content-Length是不会在这里面指定的。因为使用了Transfer-Encoding: chunked,每次发送的数据都是有一个结束标志的,根据那个结束标志判断当前传输是结束的,总的数据传输完成之后,再发给客户端一个数据发送完毕的标志。 所以说如果指定了Transfer-Encoding: chunked,你发送数据的行为也要和http标准中的要求保持一致,否则,就把客户端给搞糊涂了。
@yunnysunny 哎呀。总之这个神一般的客户端就是要添上Connection:keep-alive才行接收完整的数据报,实现这个功能与Transfer-Encoding一起缺一不可。拜托想个添上这个协议头的办法吧。都说客户端我没法修改。别人在php上能完美运行,迁移到node.js才有这样的问题。人家是这样判断是否继续接收数据的,我也只能按别人的规则来写服务器。理论什么的之前我已经查过了,也问过他们的技术人员,不过都没解决问题。实在没办法才过来cnodejs问怎么解决罢了。只要添上这个协议头就什么问题都没有了。至少我在本地拦截数据包修改数据后得出这样的结论
@mypayne 不是说加上了Transfer-Encoding就一定能起作用,你看到有Transfer-Encoding才能起作用,只是表象,其实http在传输过程中,如果指定了Transfer-Encoding: chunked,则会将数据内容分块传输。所以你即使将Transfer-Encoding头加上也没有用。而express将node的默认传输编码方式改掉了,改成了整块传输,而且我刚才翻了一遍express的文档,没有发现可以设置传输编码的功能。 所以这个地方我能想到的解决方案是,另起一个http端口,采用存node编写http处理代码,复用之前你写的数据处理部分的代码。
@ggaaooppeenngg 如果改了头的话我用express发的别的包也会捎上这个Connection:keep-alive 不知道会不会又出状况 = = 我先试一下。如果这样加都不行那目测就是node.js的问题了
@mypayne express的Transfer-Encoding就不是chunked模式,你现在用express有啥用,除非你修改了编码传输方式,改成chunked模式,否则你的客户端应该就不会正确接收数据了。