问题1:UDP模块的socket的内部签名是什么?
Socket {
domain: null,
_events: { message: [Function], listening: [Function] },
_eventsCount: 2,
_maxListeners: undefined,
_handle:
UDP {
fd: undefined,
lookup: [Function: lookup4],
owner: [Circular],
onmessage: [Function: onMessage] },
_receiving: true,
_bindState: 2,
type: 'udp4',
fd: -42,
_reuseAddr: undefined }
注意:这个socket是一个EventEmitter实例而不是一个stream,相对于TCP来说其socket既是Stream实例也是EventEmitter实例。
server.on('message',function(msg,rinfo){
//第二个参数签名为
console.log(rinfo);
console.log('server got:'+msg+" from "+rinfo.address+":"+rinfo.port);
})
server.on('listening',function(){
//server对象的签名为
var address=server.address();
console.log('server listening '+address.address+":"+address.port);
});
//下面让UDP套接字接受网络消息,这个套接字接受所有网卡上6666端口号的消息,在绑定完成之后触发listening事件
server.bind(6666);
这时候我们服务器绑定了6666端口号,在listening中可以获取到当前服务器绑定的URL和端口号。通过
server.address方法就可以获取到服务器运行的地址。而message中事件中,其通过第二个参数rinfo可以获取来源的地址。我们看看message事件中获取到的来源的信息:
{ address: '127.0.0.1', family: 'IPv4', port: 55168, size: 12 }
注意:也就是说这个服务器运行以后监听了网卡上的一个端口号,不管UDP客户端从那台主机发送消息都是可以接收到的,只要他是发送到UDP服务器监听的端口号就可以
问题2:Class: dgram.Socket有哪些事件和方法?
通过dgram.createSocket来创建,而且不需要通过new操作符
Event: 'close'
当socket通过close方法关闭的时候触发,如果触发了,那么就不会在这个socket上触发任何"message"事件。
Event: 'error'
当抛出异常的时候触发
Event: 'listening'
当socket对象开始监听数据包文的信息触发,当UDP socket被创建的时候就会触发
Event: 'message'
第一个参数为Buffer对象,第二个参数为远程地址信息。
socket.on('message', (msg, rinfo) => {
console.log('Received %d bytes from %s:%d\n',
msg.length, rinfo.address, rinfo.port);
});
socket.addMembership(multicastAddress[, multicastInterface])
const dgram = require('dgram');
const server = dgram.createSocket('udp4');
server.on('error', (err) => {
console.log(`server error:\n${err.stack}`);
server.close();
});
server.on('message', (msg, rinfo) => {
console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
});
server.on('listening', () => {
var address = server.address();
console.log(`server listening ${address.address}:${address.port}`);
});
server.bind(41234);
// server listening 0.0.0.0:41234
上面这个例子使用UDP监听41234端口号
socket.bind({
address: 'localhost',
port: 8000,
exclusive: true
});
socket.close([callback])
const dgram = require('dgram');
const message = new Buffer('Some bytes');
const client = dgram.createSocket('udp4');
client.send(message, 0, message.length, 41234, 'localhost', (err) => {
client.close();
});
UDP报文的大小:
IPV4/IPV6最大的报文大小取决于MTU (Maximum Transmission Unit)和Payload Length字段大小。Payload Length字段是16比特的长度,也就是正常载荷超过64KB(包含报文头和数据)(65,507 bytes = 65,535 − 8 bytes UDP header − 20 bytes IP header)。对于环回接口这个值都是正确的,但是这么大的数据报文信息对于大多数主机和网络来说都是不适用的。MUT指的是指定的链路层基础能够支持的最大的数据报文信息。对于IPV4指定的MTU最小为68字节,但是对于IPV4建议的大小为576。
对于IPV6来说,其最小的MTU是1280字节,强制最小片段的缓存大小为1500字节。68个字节太小了,因为大多数链路技术,如以太网,都有最小的MTU为1500字节。发送一个超过接受者能够接受的MTU将不会起作用,因为报文就会悄悄的丢掉,而不会告诉发送者数据没有发送成功。
socket.setBroadcast(flag)
设置或者清除SO_BROADCAST这个socket选项,当设置为true的时候,那么UDP报文就会发送到一个本地网卡的广播地址。
socket.setMulticastLoopback(flag)
设置或者清除socket连接的IP_MULTICAST_LOOP(也就是IP多播回环)。如果设置为true的时候多播报文也会被本地网卡接受
socket.setMulticastTTL(ttl)
设置socket的IP_MULTICAST_TTL选项,TTL代表'Live to Live',在这里用于一个报文允许经过的最大的跳数,当然是对于多播来说的。每经过一个路由和网关那么TTL就会减少1,如果减少为0那么不会传输。参数的范围为0~255,大多数系统默认为1.
socket.setTTL(ttl)
设置socket对象的IP_TTL选项,在这种情况下代表能经过的跳数的数量。常用于网络寻址或者多播。ttl在0~255之间,大多数系统都是64
socket.ref()
默认情况下,绑定一个socket就会阻塞Node.js进程,只要这个socket打开那么就会一直阻塞。socket.unref()就会把当前socket排除在引用计数外。socket.ref相反会把当前socket重新添加到引用计数之中,同时重新加载这个socket的默认行为。因为这个方法可以返回一个socket,因此可以接受链式调用
socket.unref()
这个方法允许把当前socket排除在引用计数之外,我们知道这些引用会导致Node.js进程一直保持活动。这个方法允许在当前socket处于活动态的时候自己退出
dgram.createSocket(options[, callback])
这个方法会产生一个