Nodejs中我在客户端始终无法响应res的send事件,小白提问。

Nodejs中我在客户端始终无法响应res的send事件,小白提问。

 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)事件始终没有反应……这是为什么?


10 回复

您遇到的问题可能是由于服务器端处理请求时的某些细节问题导致的。让我们先简化一下您的代码,并确保客户端和服务器端的逻辑正确无误。

客户端代码

首先,我们来简化客户端代码,使其更加清晰:

const http = require('http');
const qs = require('querystring');

// 需要提交的数据
const post_data = { a: 123, time: new Date().getTime() };
const content = qs.stringify(post_data);

const options = {
  host: 'localhost',
  port: 3000,
  path: '/',
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': Buffer.byteLength(content),
  },
};

console.log("post options:\n", options);
console.log("content:", content);
console.log("\n");

const req = http.request(options, (res) => {
  let _data = '';

  res.on('data', (chunk) => {
    _data += chunk;
  });

  res.on('end', () => {
    console.log('end is emitted');
    console.log("\n---\nresult:", _data);
  });
});

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

服务器端代码

接下来,我们来优化服务器端代码,确保其正确处理请求并响应客户端:

const http = require('http');
const qs = require('querystring');

http.createServer((req, res) => {
  let data = '';

  req.on('data', (chunk) => {
    data += chunk;
  });

  req.on('end', () => {
    const parsedData = qs.parse(data);
    console.log(parsedData.a); // 打印解析后的数据

    res.writeHead(200, {
      'Content-Type': 'text/plain',
    });

    res.write(parsedData.a.toString()); // 返回解析后的值
    res.end('hello'); // 结束响应
  });
}).listen(3000, () => {
  console.log("Server is listening on port 3000");
});

关键点解释

  1. Content-Length: 在客户端设置 Content-Length 时,使用 Buffer.byteLength(content) 而不是直接计算字符串长度,以确保正确计算二进制数据的长度。

  2. 服务器端处理:

    • 确保在 req.on('end') 事件中处理数据,而不是在外部。
    • 使用 qs.parse(data) 解析接收到的数据,并将其返回给客户端。
  3. 响应结束:

    • 在发送响应后,记得调用 res.end() 来确保响应完整结束。

通过这些调整,客户端的 res.on('end') 事件应该能够正常触发,并且您可以正确地接收服务器端的响应。


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貼在一起了

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

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

从你的描述来看,问题可能出在客户端和服务端的通信上。在客户端代码中,你使用了 http.request 方法来发送 POST 请求,但在服务端的处理过程中,可能存在一些问题导致客户端的 res.on('end') 事件没有被触发。

以下是修正后的示例代码,确保服务端正确处理请求并返回数据:

客户端代码

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;
  });

  res.on('end', function () {
    console.log('end is emitted');
    console.log("\n---\nresult:", _data);
  });
});

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

服务端代码

var http = require('http');
var qs = require('querystring');

http.createServer(function (req, res) {
  var data = '';

  req.on('data', function (chunk) {
    data += chunk;
  });

  req.on('end', function () {
    data = qs.parse(data);
    console.log(data.a); // 输出解析后的数据
    res.writeHead(200, {
      'Content-Type': 'text/plain'
    });
    res.write(data.a.toString());
    res.end(); // 确保结束响应
  });
}).listen(3000);

console.log("Server is listening on port 3000");

解释

  1. 客户端代码:

    • 发送 POST 请求到指定路径,并设置请求头。
    • http.request 的回调函数中,监听 dataend 事件来处理响应数据。
  2. 服务端代码:

    • 创建一个 HTTP 服务器,监听 / 路径的 POST 请求。
    • req.on('end') 回调中,解析请求体中的数据,并将其作为响应内容返回。
    • 使用 res.end() 确保响应正确结束。

通过这些修改,应该可以解决你在客户端无法响应 res.on('end') 事件的问题。确保服务端正确处理请求并返回数据。

回到顶部