我在客户端始终无法响应res的end事件,小白提问。
发布于 11 年前 作者 ggaaooppeenngg 5721 次浏览 最后一次编辑是 8 年前
 var http=require('http');
  var qs=require('querystring');
  var post_data={a:123,time:new Date().getTime()};//这是需要提交的数据
  var content=qs.stringify(post_data);

  var options = {
    host: 'localhost',
    port: 3000,
    path: '/',
    method: 'POST',
    headers:{
    'Content-Type':'application/x-www-form-urlencoded',
    'Content-Length':content.length
    }
  };
  console.log("post options:\n",options);
  console.log("content:",content);
  console.log("\n");

  var req = http.request(options, function(res) {
    console.log("statusCode: ", res.statusCode);
    console.log("headers: ", res.headers);
    var _data='';
    res.on('data', function(chunk){
       _data += chunk;
      console.log(_data);
    });
    res.on('end', function(){
       //data = qs.parse(_data);
      console.log('end is emitted');
      console.log("\n--->>\nresult:",_data)
    });
  });

  req.write(content);
  req.end();

  //服务器
  var http = require('http');
  var url = require('url');
  var util = require('util');
  var qs = require('querystring');
  http.createServer(function(req,res){
    var data = '';
      req.on('data',function(chunk){
          data+=chunk;
      });

  req.on('end',function(){
      res.writeHead(200, {
        'Content-Length': data.length,
      'Content-Type': 'text/plain' });
      data = qs.parse(data);
      console.log(data.a.toString());
      res.write(data.a.toString());
      res.end('hello');
      //data = qs.parse(data);
      console.log(data);
  });
  }).listen(3000);
  console.log("!!!");

在客户端 我的res.on(end)事件始终没有反应……这是为什么?

25 回复

req.on(‘end’) ?

哥哥,你的req.end()调用的时候服务器还没启动呢?我给你的代码稍微改了下. req.write(content);req.end();放到.listen(3000);的回调函数里面得到了你想要的结果. <pre><code> listen(3000,function(){ req.write(content); req.end(); }); </pre></code>

经过哥的深入分析,原来是这里的问题:

res.writeHead(200, {
        'Content-Length': data.length,      // 应该去掉这一行
      'Content-Type': 'text/plain' });

一般情况下是不需要自己去手动设置这个 Content-Length 的,但是你奇葩地去做了; 如果你没有设置 Contebt-Length ,http模块内部是会自动帮你计算的,但是你设置了这个值,而你实际返回的数据长度却没有这么多,于是http客户端请求时就在那傻傻地等(即使你已经 res.end() 了),直到连接关闭后才触发 end 事件。

设置了不正确的 Content-Length 的后果就是,如果实际数据长度超过了这个值,后面会被截断,如果实际没有这么大,就形成了 “无法触发end事件” 的假象。

呵呵,这里的长度是对的,看看我的评论,我亲自运行了是正常的.

是Content-Length的問題沒錯

參照:

http://nodejs.org/api/http.html#http_response_writehead_statuscode_reasonphrase_headers

Note: that Content-Length is given in bytes not characters. The above example works because the string 'hello world' contains only single byte characters. If the body contains higher coded characters then Buffer.byteLength() should be used to determine the number of bytes in a given encoding. And Node does not check whether Content-Length and the length of the body which has been transmitted are equal or not.

我猜他是Server.js跟Client.js分開的。

只是他把Server & Client的Code貼在一起了

@hankwang 楼主这里发送的数据都是单字节字符a=123&time=1373436320245,这个数值没有错,我亲自运行了这个代码,是可以正常工作的.

@dengqiao 长度对个毛啊

res.writeHead(200, {
  'Content-Length': data.length,      // 这里的data是客户端提交上来的数据,内容大概为 {"a":123,"time":1373443826951}
  'Content-Type': 'text/plain' });
data = qs.parse(data);
console.log(data.a.toString());
res.write(data.a.toString());        // 这里的内容是 123
res.end('hello');                    // 这里的内容是 hello
                                     // 两个加起来的话就是 123hello

而你在评论中给出的例子:

listen(3000,function(){
    req.write(content);
    req.end();
});

写得如此马虎, req 变量从哪里的? 有 req.end() 的么? 你这代码的运行结果是你口算出来的吧?!

@dengqiao 纠正一下,上面说的data的内容大概是 a=123&time=1373444684836

@leizongmin 我估计你没好好看我的评论

@dengqiao 我肯定你没好好看我的评论: 如果 data 是 “a=123&time=1373444684836”, data.length 的值为 24 服务器返回的内容是 “123hello”, 其长度为 8

@leizongmin sorry,response的时候长度是有问题,但是我运行的时候request确实是获取到了结果

@dengqiao 看清人家的问题 “我在客户端始终无法响应res的end事件,小白提问。”

@leizongmin 我说的结果就是获取到了res的end事件,输出 end is emitted

—>> result: 123hello

谢谢各位,我明白了!!!!!! 万分感谢!!!!

@ggaaooppeenngg 到底咋回事啊?搞的我们吵了这么长时间.

@dengqiao 应该是我的报文头写的数据长度太长了,跟我实际传的不一样,而且NODEJS不负责检查这部分,所以导致客户端一直在等我传我数据。

@ggaaooppeenngg 不是Node.js不负责检查,而是本来就不需要你自己去指定 Content-Lenght 的,你设置了这个值却是不正确反而会出问题。

@ggaaooppeenngg 在这个例子中,你执行 res.writeHead() 都是多余的:默认响应的statusCode就是200,Content-Lenght是自动计算的,Content-Type是text/plain

@leizongmin 没细看帖子,好像是content-length设置不对造成的吧,改用这个头把,一劳永逸 Transfer-Encoding: chunked

@snoopy 默认就是 Transfer-Encoding: chunked 的,你这个也算是 脱裤子放屁

@leizongmin 汗。。你要告诉楼主Conteng-Length和Transfer-Encoding的区别和应用场景。我这个是规范,哈哈,虽然属于多此一举。脱裤子放屁真是俗的

奇怪在我这里是好的,node 版本0.10.12

@leizongmin 哈哈,在我的0.6.12上不行不到end,在0.10.12上可以相应end

@leizongmin @snoopy @hankwang 跟我设想的一样,0.10.12版本可以运行成功的原因是客户端header中没有Connection: 'keep-alive’服务器在服务完请求后会关闭connection,这样在0.10.12版本中触发了end事件,这个应该是node在后续中的一个改进,我在楼主的代码中加上Connection: 'keep-alive’在0.10.12版本中就无法触发end事件了.

回到顶部