TCP服务
- 传输控制协议,网络传输层
OSI模型
: 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层
传输之前先要三次握手形成会话,一个套接字socket只用于一个服务
创建TCP服务
|
|
也可以对Domain Socket监听 server.listen(‘/tmp/echo.sock’);
使用 $ nc -U /tmp/echo.sock 测试
服务器事件
使用net.createServer()创建的服务器是个EventEmitter实例
- listening 在调用server.lisren()绑定端口或者Domain Socket后触发server.listen(port,listeningListener)
- connection 每个客户端套接字连接到服务端时触发 net.createServer(),最后一个参数传递
- close 当服务器关闭时触发 在调用server.close()后,服务器会停止接受新的套接字,但当前的连接不会断,直到所有连接都断后触发
- error 服务器发生异常时触发,如果不帧听error事件,会抛出异常
连接事件
服务器可以同时与多个客户端保持连接,每个连接都是可读写的stream对象,用于服务器和客户端通信
- data 当一端调用write()发送数据时,另一端触发data事件
- end 任意一端发送了FIN数据时触发
- connect 用于客户端,当套接字与服务端连接成功时触发
- error 发生异常
- close 套接字完全关闭时触发
- timeout 连接在一定时间内部活跃,触发
|
|
Nagle算法
:将tcp中的小数据包缓存合并到一定数量或时间后发出,避免浪费网络资源,但数据可能被延迟。tcp默认启动Nagle算法,可以调用socket.setNoDelay(true)关闭,关闭后一端调用write(),另一端可能将多个小数据包合并后触发一次data
UDP服务
- 用户数据包协议,网络传输层
- 一个套接字可以和多个UDP服务通信,无须连接,资源消耗低,处理快速灵活
- 可能丢包,应用在低丢包不影响的的场景,视频、DNS
创建UDP套接字
UDP套接字可以做客户端也可做服务端
- 作为服务端 调用dgram.bind(port,[address])方法对网卡和端口绑定
|
|
- 作为客户端:使用dgram.send(buf, offset, length, port, address, [callback])发送消息到网络;参数对应含义,buffer,buffer偏移,buffer长度,目标端口,目标地址,发送完成后的回调。它可以随意发送数据到网络,tcp需要重新通过套接字构建新连接
|
|
UPD套接字事件
- UDP是个EventEmitter实例使用更简单,TCP是个Stream实例
- message UDP套接字帧听网卡端口后,接受数据时触发,触发携带的数据为Buffer对象和远程地址
- listening UDP开始帧听时触发
- close 调用close()时触发,并不再触发message事件
- error 异常时触发,不帧听则直接抛出,进程退出
构建HTTP服务
- 超文本传输协议 HyperText Transfer Protocol
- 构建在TCP之上 属于应用层协议 B/S模式,目前最知名的标准RFC 2616
通常的http通信的信息分三部分,TCP的3次握手,客户端向服务器发送请求报文,服务器完成处理后向客户端发送响应内容。
浏览器其实是http的代理,将用户的行为转化为http请求发送给服务端,服务端处理请求然后发送响应报文给代理,代理解析报文再展示给用户。http服务只做处理http请求和发送http响应
|
|
http模块
- 继承自TCP服务(net模块),通信方法都是使用net的,包括创建服务、关闭服务等
- 能够与多个客户端保持连接,因为采用事件驱动,不用给每个连接创建额外的线程、进程,内存占用低,能高并发
- tcp以connection为单位服务,http以request为单位服务
http模块将tcp连接的读操作封装为ServerRequest对象,报文头部使用http_parser解析然后放在req.headers上传递给业务逻辑。报文体部分为只读流对象,需要在数据流结束后转字符串
|
|
封装对底层连接的写操作为ServerResponse对象
影响响应报文头api为res.setHeader()和res.writeHead(),可以调用res.setHeader()进行多次设置,只要调用writeHead后,报头才会写入连接
|
|
设置报文体API为write(),end();end()会先调用write()发送数据,再发信号告知响应结束。
一旦开始了数据发送,writeHead()和setHeader()将不再生效
结束时要调用res.end(),否则客户端将一直处于等待状态,无论异常与否
http服务端事件
http服务器是个EventEmitter实例
- connection 客户端与服务器建立底层的tcp连接时触发。连接开启keep-alive,可以在多次请求响应之间使用
- request 当请求数据发送到服务端,在解析出http请求头后触发该事件
- close 调用server.close()方法停止接受新连接,当已有的连接也都断开后触发,可以给server.close()传个回调来快速注册该事件
- checkContinue 某些客户端在发送大数据时,会先发一个头部带Expect: 100-continue的请求,服务器接收后触发checkContinue。如果不监听,就自动回复100 Continue。如果不接收就响应400 Bad Request。注意,在客户端收到100 Continue后重新发起请求才会触发request
- connect 客户端发起connect请求时触发,通常在http代理时才会发起connect,如果不监听,发起该请求的连接会关闭
- upgrade 客户端要升级连接协议时会在请求头部带上upgrade,服务端接收后触发,如果不监听,发起该请求的连接会关闭
- clientError 连接的客户端触发error事件,会传递到服务器端并触发
http客户端
- http.request(options, connect) 构建http客户端
|
|
报文体的内容通过请求对象的write()写入,end()告知报文结束
客户端clientRequest(req)解析完响应头就触发response,并传递ClientResponse以供操作,之后报文体以只读流提供)
http代理
- 为了重用tcp连接(在keeplive时,一个tcp连接可以多次用于请求)
- http里包含一个客户端代理对象http.globalAgent,它管理每个服务端(host+port)创建的连接并创建一个连接池,默认每个服务器端5个连接
在通过ClientRequest调用http请求时会走代理。可以在options中传递agentX修改连接限制
|
|
http客户端事件
- response 客户端得到响应后触发
- socket 当连接池中建立的连接分配给当前的对象时触发
- upgrade 客户端向服务端发起upgrade 服务端响应101 Switching Protocols时触发
- continue 客户端想发大数据,头部带Expect: 100-continue,服务端同意并响应100 continue时触发