node 网络(一)

2016-08-12  本文已影响0人  wmtcore

TCP服务

传输之前先要三次握手形成会话,一个套接字socket只用于一个服务

创建TCP服务

 var net = require('net');
 
//使用net.createServer(listener)创建,**listener是连接事件connection的侦听器**
var server = net.createServer(function(socket) {
    socket.on('data', function(data) {
        socket.write("hello");
    });
    socket.on('end', function() {
        console.log('断开');
    });
    socket.write("hello111:\n");
});
server.listen(8124, function() {
    console.log('server bound');
}); 
//或者
var server = net.createServer();

server.on('connection', function(socket) { //新的连接
});
server.listen(8124);

//可以使用$ telnet 127.0.0.1 8124,或者使用net模块构建客户端
var net = require('net');
var client = net.connect({  //
    port: 8124
}, function() { //'connect' listener
    console.log('client connected');
    client.write('world!\r\n');
});
client.on('data', function(data) {
    console.log(data.toString());
    client.end();
});
client.on('end', function() {
    console.log('client disconnected');
});

也可以对Domain Socket监听 server.listen('/tmp/echo.sock');
使用 $ nc -U /tmp/echo.sock 测试

服务器事件

使用net.createServer()创建的服务器是个EventEmitter实例

  1. listening 在调用server.lisren()绑定端口或者Domain Socket后触发server.listen(port,listeningListener)
  2. connection 每个客户端套接字连接到服务端时触发 net.createServer(),最后一个参数传递
  3. close 当服务器关闭时触发 在调用server.close()后,服务器会停止接受新的套接字,但当前的连接不会断,直到所有连接都断后触发
  4. error 服务器发生异常时触发,如果不帧听error事件,会抛出异常

连接事件

服务器可以同时与多个客户端保持连接,每个连接都是可读写的stream对象,用于服务器和客户端通信

  1. data 当一端调用write()发送数据时,另一端触发data事件
  2. end 任意一端发送了FIN数据时触发
  3. connect 用于客户端,当套接字与服务端连接成功时触发
  4. error 发生异常
  5. close 套接字完全关闭时触发
  6. timeout 连接在一定时间内部活跃,触发
//使用pipe管道 管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。

var net = require('net');
var server = net.createServer(function(socket) {
    socket.write('Echo server\r\n');
    socket.pipe(socket);//
});
server.listen(1337, '127.0.0.1');

Nagle算法:将tcp中的小数据包缓存合并到一定数量或时间后发出,避免浪费网络资源,但数据可能被延迟。tcp默认启动Nagle算法,可以调用socket.setNoDelay(true)关闭,关闭后一端调用write(),另一端可能将多个小数据包合并后触发一次data

UDP服务

创建UDP套接字

UDP套接字可以做客户端也可做服务端

var dgram = require('dgram');
var server = dgram.createSocket('udp4');
server.on("message", function(msg, rinfo) {
    console.log("server got: " + msg + " from " +
        rinfo.address + ":" + rinfo.port);
});
server.on("listening", function() {
    var address = server.address();
    console.log("server listening " + address.address + ":" + address.port);
});
server.bind(41234);//绑定完成后触发listening事件
var dgram = require('dgram');
var message = new Buffer("Node.js");
var client = dgram.createSocket("udp4");
client.send(message, 0, message.length, 41234, "localhost", function(err, bytes) {
    client.close();
});

UPD套接字事件

  1. message UDP套接字帧听网卡端口后,接受数据时触发,触发携带的数据为Buffer对象和远程地址
  2. listening UDP开始帧听时触发
  3. close 调用close()时触发,并不再触发message事件
  4. error 异常时触发,不帧听则直接抛出,进程退出

构建HTTP服务

通常的http通信的信息分三部分,TCP的3次握手,客户端向服务器发送请求报文,服务器完成处理后向客户端发送响应内容。
浏览器其实是http的代理,将用户的行为转化为http请求发送给服务端,服务端处理请求然后发送响应报文给代理,代理解析报文再展示给用户。http服务只做处理http请求和发送http响应

http模块

http模块将tcp连接的读操作封装为ServerRequest对象,报文头部使用http_parser解析然后放在req.headers上传递给业务逻辑。报文体部分为只读流对象,需要在数据流结束后转字符串

function(req, res) {
    // console.log(req.headers);
    var buffers = [];
    req.on('data', function(trunk) {
        buffers.push(trunk);
    }).on('end', function() {
        var buffer = Buffer.concat(buffers); // TODO
        res.end('Hello world');
    });
}
//express中使用bodyParse,会自动解析,但要求请求头添加Content-Type=application/json

封装对底层连接的写操作为ServerResponse对象
影响响应报文头api为res.setHeader()res.writeHead(),可以调用res.setHeader()进行多次设置,只要调用writeHead后,报头才会写入连接

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

设置报文体API为write(),end();end()会先调用write()发送数据,再发信号告知响应结束。

一旦开始了数据发送,writeHead()和setHeader()将不再生效
结束时要调用res.end(),否则客户端将一直处于等待状态,无论异常与否

http服务端事件

http服务器是个EventEmitter实例

http客户端


var options = {
    hostname: '127.0.0.1',
    port: 1334,
    path: '/',
    method: 'GET',
    localAddress //建立连接的本地网卡
    socketPath //Domain套接字路径
    headers //请求头对象
    auth //Basic认证 将被计算成请求头的Authorization部分
};
// 用request 包请求 不用自己来处理on end 
var req = http.request(options, function(res) {
    console.log('STATUS: ' + res.statusCode);
    console.log('HEADERS: ' + JSON.stringify(res.headers));
    res.setEncoding('utf8');
    res.on('data', function(chunk) {
        console.log(chunk);
    });
});

req.end();

报文体的内容通过请求对象的write()写入,end()告知报文结束
客户端clientRequest(req)解析完响应头就触发response,并传递ClientResponse以供操作,之后报文体以只读流提供)

http代理

在通过ClientRequest调用http请求时会走代理。可以在options中传递agentX修改连接限制

var agent = new http.Agent({
    maxSockets: 10 
});
var options = {
    hostname: '127.0.0.1',
    port: 1334,
    path: '/',
    method: 'GET',
    agent: agent //设置为false就不受连接池限制
};

http客户端事件
上一篇 下一篇

猜你喜欢

热点阅读