res.end与req.end之间的区别与联系(向本地服务器请求数据中遇到的问题)

本文探讨了在NodeJS中,HTTP服务器处理请求时res.end()和req.end()的区别。通过实验验证,作者发现res.end()标志着连接的结束,而req.end()可能在res.end()之前执行,导致服务器仍能接收数据。同时,req.end()并不能直接断开连接,但连续调用会导致数据发送被阻断。当客户端req.end()时,服务端通常会监听end事件并相应地调用res.end()来结束连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

这是我在阅读NodeJS权威指南一书时遇到的问题

代码

用于接受数据的HTTP服务器

var  http = require('http');
var server = http.createServer(function(req,res){
    if(req.url!=='/favicon.ico'){      
       req.on('data',function(data){
            console.log('服务器端接收到数据:'+data);
            res.end();
        })
    }
}).listen(1337,'127.0.0.1');

用于发送数据的HTTP客户端

var http = require('http');
var options = {
    hostname:'localhost',
    port:1337,
    path:'/',
    method:'POST'
};
var req = http.request(options);
req.write('你好');
req.end('再见')

结果

服务器端接收到数据:你好。
服务器端接收到数据:再见。

问题

我的问题在于,当客户端对服务器发起请求,并且用write发送数据时,将触发服务器端的data事件,而data事件中的res.end()方法将结束服务器与客户端之间的连接,
在这里插入图片描述

那么为什么断开连接之后,服务器还能收到 req.end(‘再见’) 呢?

猜想

针对这个问题,我提出了两个猜想:

  1. 客户端向服务器端发送了两次请求
  2. 客户端的 req.end(‘再见’) 的发送的比服务器端的 res.end() 的执行要来的快

验证

首先我们来验证第一个猜想:客户端向服务器端发送了两次请求

在一次连接中console.log(1)

var server = http.createServer(function(req,res){
    if(req.url!=='/favicon.ico'){
        console.log(1);
        req.on('data',function(data){
            console.log('服务器端接收到数据:'+data);
            res.end()
        })
    }
}).listen(1337,'127.0.0.1');

在这里插入图片描述
发送了两个数据,只打出一个1,因此只进行了一次连接,那么猜想一显然不成立

那么我们再来验证第二个猜想:客户端的 req.end(‘再见’) 的发送的比服务器端的 res.end() 的执行要来的快

我们对客户端代码进行下列修改:给 **req.end(’再见’)**设置一个定时器,让它延迟两秒后再进行

var http = require('http');
var options = {
    hostname:'localhost',
    port:1337,
    path:'/',
    method:'POST'
};
var req = http.request(options);
req.write('你好')
setTimeout(function(){
    req.end('再见')
},1000)

在这里插入图片描述
服务器只收到了一个你好,这说明,由于延迟了一秒,导致服务器端的 res.end() 方法提前于,客户端的 req.end(‘再见’) 方法执行,导致连接断开,客户端不能再将数据发送给服务器,从而我们可以推测,在这之前服务器能够接收到客户端的数据,是由于客户端的 req.end(‘再见’) 方法先于服务器的 res.end() 方法执行

那么我还有一个问题,res.endreq.end 两个方法的区别是什么?res.end标志着连接的断开,那么 req.end呢?如果 req.end不表示连接的断开,那么 req.end方法执行后,客户端还能向服务器发送数据吗?如果还可以的话,req.end方法的意义在哪里呢?

var http = require('http');
var options = {
    hostname:'localhost',
    port:1337,
    path:'/',
    method:'POST'
};
var req = http.request(options);
req.write('你好')
req.end('再见')
req.write('你好')

在这里插入图片描述
服务器报错了

那么req.end(‘再见’)后可以再利用req.end方法发送数据吗?
我们再req.end(‘再见’)后加上req.end(‘你好’)

var http = require('http');
var options = {
    hostname:'localhost',
    port:1337,
    path:'/',
    method:'POST'
};
var req = http.request(options);
req.write('你好')
req.end('再见')
req.end('你好')

在这里插入图片描述
显然,还是不行。这说明虽然req.end不能直接断开连接,但是却可以阻断数据的发送。

我们一般会在服务端设置一个req的end事件,当客户端的end事件发生时,将会触发该事件,代码如下所示,在下面的代码中,当触发了req的end事件之后,服务端就会执行res.end()方法,断开与客户端之间的连接

//用于接收数据的http服务器
var  http = require('http');
var server = http.createServer(function(req,res){
    if(req.url!=='/favicon.ico'){
        console.log(1);
        req.on('data',function(data){
            console.log('服务器端接收到数据:'+data);
            res.end()
        })
        req.on('end',function(){
            res.end();
         })
    }
}).listen(1337,'127.0.0.1');
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值