forNodejs源码分析转载请联系编程杂技公众号。让我们从一个使用示例开始,看看udp模块的实现。constdgram=require('dgram');//创建socket对象constserver=dgram.createSocket('udp4');//监听udp数据的到来server.on('message',(msg,rinfo)=>{//处理数据});//绑定端口server.bind(41234);我们看到创建udp服务器很简单,首先申请一个socket对象,在nodejs中和操作系统中是一样的,socket是一个网络通信的抽象,我们可以把它理解为传输层的一个抽象,它可以代表tcp或udp。我们来看看createSocket是干什么的。functioncreateSocket(type,listener){returnnewSocket(type,listener);}functionSocket(type,listener){EventEmitter.call(this);letlookup;letrecvBufferSize;letsendBufferSize;letoptions;if(type!==null&&typeoftype==='object'){options=type;type=options.type;lookup=options.lookup;recvBufferSize=options.recvBufferSize;sendBufferSize=options.sendBufferSize;}constandle=newHandle(type,lookup);this.type=type;if(typeoflistener==='function')this.on('message',listener);this[kStateSymbol]={handle,receiving:false,bindState:BIND_STATE_UNBOUND,connectState:CONNECT_STATE_DISCONNECTED,queue:undefined,reuseAddr:options&&options.reuseAddr,//UseUV_UDP_REUSEADDRiftrue.ipv6Only:options&&options.ipv6Only,recvBufferSize,sendBufferSize};}我们看到一个socket对象是对handle的一个封装。我们看handle是什么。functionnewHandle(type,lookup){//dns解析的函数,比如我们调用send时,传入一个域名if(lookup===undefined){if(dns===undefined){dns=require('dns');}lookup=dns.lookup;}if(type==='udp4'){consthandle=newUDP();handle.lookup=lookup4.bind(handle,lookup);returnhandle;}//忽略ipv6的processing}handle是对UDP模块的封装,UDP是一个c++模块,我们看一下c++模块的定义。//定义一个v8函数模块Localt=env->NewFunctionTemplate(New);//新创建的t对象需要额外扩充内存t->InstanceTemplate()->SetInternalFieldCount(1);//导出到js中层使用的名称LocaludpString=FIXED_ONE_BYTE_STRING(env->isolate(),"UDP");t->SetClassName(udpString);//属性访问属性enumPropertyAttributeattributes=static_cast(ReadOnly|DontDelete);Localsignature=Signature::New(env->isolate(),t);//新建一个函数模块Localget_fd_templ=FunctionTemplate::New(env->isolate(),UDPWrap::GetFD,env->as_callback_data(),signature);//设置访问器,访问fd属性时,执行get_fd_templ,从而执行UDPWrap::GetFDt->PrototypeTemplate()->SetAccessorProperty(env->fd_string(),get_fd_templ,Local(),attributes);//导出函数env->SetProtoMethod(t,"open",Open);//忽略一系列函数//使用target->Se导出到js层t(env->context(),udpString,t->GetFunction(env->context()).ToLocalChecked()).Check();在c++层的通用逻辑中,我们相关知识我已经讲过了,这里就不赘述了。当我们在js层新建UDP时,会新建一个c++对象UDPWrap::UDPWrap(Environment*env,Local